How to use Group By and self-join to return min, max, open, and close daily price restult set?

前端 未结 2 832
广开言路
广开言路 2021-01-15 17:39

SOLVED

All hail StackOverlow!

While I was gone, people left 2 solutions (thanks guys--what is the protocol for handing out karma for two wor

相关标签:
2条回答
  • 2021-01-15 18:16

    So you want:

    • The alias C to correspond to all rows in the group for a given day, so you can use MAX() and MIN() over the rows in that group.
    • The alias C2 to correspond to the last row in a given day.
    • The alias C3 to correspond to a row later than C2 on the same day. If none is found, i.e. C3.* is NULL, then C2 is the latest on that day.

    This is often labeled a greatest-n-per-group query, and it comes up frequently on Stack Overflow. Here's a solution that I tested for your test data, but you can follow the tag I added to your question for other solutions and discussion.

    edit: I missed the requirement for both opening price and closing price. The following is edited.

    SELECT DATE_FORMAT(C.`DTE`, '%m/%d/%Y') AS trading_day, 
      MIN(C.`PRICE`) AS min_price, 
      MAX(C.`PRICE`) AS max_price, 
      Copen.`PRICE` AS opening_price,
      Cclose.`PRICE` AS closing_price 
    FROM `CHART_DATA` AS C 
    INNER JOIN `CHART_DATA` AS Cclose 
      ON DAY(C.`DTE`) = DAY(Cclose.`DTE`) 
    LEFT OUTER JOIN `CHART_DATA` AS Cclose_later 
      ON DAY(C.`DTE`) = DAY(Cclose_later.`DTE`) AND Cclose.`DTE` < Cclose_later.`DTE`
    INNER JOIN `CHART_DATA` AS Copen 
      ON DAY(C.`DTE`) = DAY(Copen.`DTE`) 
    LEFT OUTER JOIN `CHART_DATA` AS Copen_earlier 
      ON DAY(C.`DTE`) = DAY(Copen_earlier.`DTE`) AND Copen.`DTE` < Copen_earlier.`DTE`
    WHERE Cclose_later.`DTE` IS NULL AND Copen_earlier .`DTE` IS NULL 
    GROUP BY trading_day;
    
    0 讨论(0)
  • 2021-01-15 18:17
    SELECT
      a.trading_day, a.min_price, a.max_price, 
      b.price as opn_price, 
      c.price as cls_price
    FROM
      (SELECT 
         DATE_FORMAT(`DTE`, "%m/%d/%Y") AS trading_day,
         MIN(`PRICE`) AS min_price,
         MAX(`PRICE`) AS max_price,
         MIN(`dte`) AS open_date,
         MAX(`dte`) AS close_date
       FROM `CHART_DATA`
       GROUP BY trading_day) a
    LEFT JOIN
      `CHART_DATA` b ON b.dte = a.open_date
    LEFT JOIN
      `CHART_DATA` c ON c.dte = a.close_date
    

    Note: this solution may present some problems if your opening or closing entry has the exact same date/time value as another row (i.e. the transaction that came immediately after opening, or immediately before closing). To address this, I would suggest that you add a sequence number that is stored in a way that guarantees uniqueness, and increasing-with-respect-to-time. If you do this, then you would use the sequence value in the place of dte to replace the open_date and close_date I've used as join fields in my example.

    0 讨论(0)
提交回复
热议问题