从交易清单中确定谨慎期间的价格

问题描述 投票:5回答:4

我有一个来自商品交易所的历史交易的谨慎清单,具有日期时间和值,例如

tradeTime                  |  price
-----------------------------------
2014-06-11T00:21:12+02:00  |  647.24
2014-06-11T00:23:12+02:00  |  700.18
2014-06-11T00:28:12+02:00  |  750.23
2014-06-11T00:40:00+02:00  |  767.81
2014-06-11T00:51:12+02:00  |  711.46

现在我希望能够每小时创建一个价格清单。所以三种逻辑可能性是:

  1. 那个时期有1笔交易 - 很棒,这就是价格(开盘和收盘)
  2. 有多个交易 - 第一个是开盘价,最后一个是收盘价
  3. 没有交易 - 开盘价和收盘价应该是该期间之前的最新交易。

因此,使用上面的示例,查看10分钟的增量,输出应该是这样的:

period         |  open    | close
--------------------------------
00:20 -> 00:30 |  648.24  | 750.23
00:30 -> 00:40 |  750.23  | 767.81
00:40 -> 00:50 |  767.81  | 711.46

-

SELECT * FROM sales BETWEEN From_date AND To_date

可能与MIN()MAX()的日期选择价格?我不确定这一切是如何与...一起来的

sql sql-server
4个回答
1
投票

试试这个查询:

WITH qq AS (
  SELECT cast('2014-06-11T00:00:00' as datetime) as startTime,
         dateadd( minute, 10, cast('2014-06-11T00:00:00' as datetime)) as endTime
  UNION ALL
  SELECT endTime, dateadd( minute, 10, endTime )
  FROM qq
  WHERE endTime < cast('2014-06-12T00:00:00' as datetime) 
)
SELECT startTime, endTime,
       coalesce( opening, opening1 ) as opening,
       coalesce( closing, opening, opening1 ) as closing
FROM (
   SELECT qq.startTime, qq.endTime,
       (SELECT TOP 1 price FROM table1 t1 
        WHERE t1.tradeTime >= qq.startTime AND t1.tradeTime < qq.endTime
        ORDER BY t1.tradeTime ) As opening,
       (SELECT TOP 1 price FROM table1 t1 
        WHERE t1.tradeTime >= qq.startTime AND t1.tradeTime < qq.endTime
        ORDER BY t1.tradeTime DESC ) As closing,
       (SELECT TOP 1 price FROM table1 t1 
        WHERE t1.tradeTime < qq.startTime
        ORDER BY t1.tradeTime DESC ) as opening1
   FROM qq
) x
option (maxrecursion 0)

但是:ぁzxswい

http://sqlfiddle.com/#!18/b9363/6

0
投票

以下查询应该给你一个开始。

|            startTime |              endTime | opening | closing |
|----------------------|----------------------|---------|---------|
| 2014-06-11T00:00:00Z | 2014-06-11T00:10:00Z |  (null) |  (null) |
| 2014-06-11T00:10:00Z | 2014-06-11T00:20:00Z |  (null) |  (null) |
| 2014-06-11T00:20:00Z | 2014-06-11T00:30:00Z |  647.24 |  750.23 |
| 2014-06-11T00:30:00Z | 2014-06-11T00:40:00Z |  750.23 |  750.23 |
| 2014-06-11T00:40:00Z | 2014-06-11T00:50:00Z |  767.81 |  767.81 |
| 2014-06-11T00:50:00Z | 2014-06-11T01:00:00Z |  711.46 |  711.46 |
| 2014-06-11T01:00:00Z | 2014-06-11T01:10:00Z |  711.46 |  711.46 |
| 2014-06-11T01:10:00Z | 2014-06-11T01:20:00Z |  711.46 |  711.46 |
| 2014-06-11T01:20:00Z | 2014-06-11T01:30:00Z |  711.46 |  711.46 |
| 2014-06-11T01:30:00Z | 2014-06-11T01:40:00Z |  711.46 |  711.46 |
| 2014-06-11T01:40:00Z | 2014-06-11T01:50:00Z |  711.46 |  711.46 |
| 2014-06-11T01:50:00Z | 2014-06-11T02:00:00Z |  711.46 |  711.46 |
...
...
...

完整示例:

 SELECT DISTINCT Disp,
       (
        CASE WHEN [Open] IS NOT NULL THEN [Open]
        ELSE (SELECT TOP 1 PRICE FROM @Table 
            WHERE Datepart(MINUTE, TradeTime) / 10 < O.Diff )
        END
       ) AS [Open]
       ,(
        CASE WHEN O.[Open] IS NOT NULL THEN [Open]
        ELSE (SELECT TOP 1 PRICE FROM @Table 
            WHERE Datepart(MINUTE, TradeTime) / 10 < O.Diff )
        END
       ) AS [Close]

       FROM
       (
        SELECT  
        D.Disp
       ,D.Diff
       ,FIRST_VALUE(Price) OVER (PARTITION BY GRP  
                           ORDER BY TradeTime ASC) AS [Open]
       ,FIRST_VALUE(Price) OVER (PARTITION BY GRP 
                           ORDER BY TradeTime DESC)  AS [Close],
        TradeTime
   FROM (VALUES (0,'00:01->00:10'),
                (1,'00:10->00:20'), 
                (2,'00:20->00:30'), 
                (3,'00:30->00:40'), 
                (4,'00:40->00:50'), 
                (5,'00:50->00:59') 
                ) D(Diff,Disp) 
        LEFT JOIN (SELECT Datepart(MINUTE, TradeTime) / 10 AS GRP, 
                         TradeTime, 
                         Price 
                  FROM   @Table 
                  GROUP  BY Datepart(MINUTE, TradeTime) / 10, 
                            TradeTime, 
                            Price) T 
                  ON T.GRP = D.Diff 
              ) O

样本输出

DECLARE @Table TABLE(TradeTime DATETIME, Price DECIMAL(15,2))
INSERT INTO @Table
  SELECT * FROM
  (VALUES 
  (CAST('2018-02-18 13:04:46.920' AS DATETIME)  ,  647.24)
 ,(CAST('2018-02-18 13:05:46.920' AS DATETIME) ,  700.18)
 ,(CAST('2018-02-18 13:15:46.920' AS DATETIME)  ,  750.23)
 ,(CAST('2018-02-18 13:24:46.920' AS DATETIME) ,  767.81)
 ,(CAST('2018-02-18 14:26:46.920' AS DATETIME)  ,  711.46)


   ) TAB(TradeTime, Price)



      SELECT DISTINCT Disp,
       (
        CASE WHEN [Open] IS NOT NULL THEN [Open]
        ELSE (SELECT TOP 1 PRICE FROM @Table 
            WHERE Datepart(MINUTE, TradeTime) / 10 < O.Diff )
        END
       ) AS [Open]
       ,(
        CASE WHEN O.[Open] IS NOT NULL THEN [Open]
        ELSE (SELECT TOP 1 PRICE FROM @Table 
            WHERE Datepart(MINUTE, TradeTime) / 10 < O.Diff )
        END
       ) AS [Close]

       FROM
       (
        SELECT  
        D.Disp
       ,D.Diff
       ,FIRST_VALUE(Price) OVER (PARTITION BY GRP  
                           ORDER BY TradeTime ASC) AS [Open]
       ,FIRST_VALUE(Price) OVER (PARTITION BY GRP 
                           ORDER BY TradeTime DESC)  AS [Close],
        TradeTime
   FROM (VALUES (0,'00:00->00:10'),
                (1,'00:10->00:20'), 
                (2,'00:20->00:30'), 
                (3,'00:30->00:40'), 
                (4,'00:40->00:50'), 
                (5,'00:50->00:59') 
                ) D(Diff,Disp) 
        LEFT JOIN (SELECT Datepart(MINUTE, TradeTime) / 10 AS GRP, 
                         TradeTime, 
                         Price 
                  FROM   @Table 
                  GROUP  BY Datepart(MINUTE, TradeTime) / 10, 
                            TradeTime, 
                            Price) T 
                  ON T.GRP = D.Diff 
              ) O

0
投票

您需要从一个小时列表开始。因为您可能没有交易,所以您需要生成此交易。假设你只需要几个小时 - 比如说一天中的所有小时 - 一个递归的CTE就足够了:

Disp            Open        Close
--------------------------------------
00:00->00:10    647.24      647.24
00:10->00:20    750.23      750.23
00:20->00:30    767.81      767.81
00:30->00:40    647.24      47.24
00:40->00:50    647.24      647.24
00:50->00:59    647.24      647.24

然后,你可以使用with hours as ( select cast('2014-06-11' as datetime) as yyyymmddhh union all select dateadd(hour, 1, yyyymmddhh) from hours where dateadd(hour, 1, yyyymmddhh) < '2014-06-12' ) 做你想做的事:

apply

0
投票

下午好,

我不确定我的解决方案是否真的对你有帮助,因为我不是在我可以检查代码是否有效或为什么没有的情况下,我会尝试这些方法:

with hours as (
      select cast('2014-06-11' as datetime) as yyyymmddhh
      union all
      select dateadd(hour, 1, yyyymmddhh)
      from cte
      where dateadd(hour, 1, yyyymmddhh) < '2014-06-12'
     )
select h.*, opening.price, closing.price
from hours h outer apply
     (select top 1 t.*
      from t
      where tradetime < dateadd(hour, 1, yyyymmddhh)
      order by (case when cast(tradetime as date) = cast(yyyymmddhh as date) and
                          datepart(hour, tradetime) = datepart(hour, yyyymddhh)
                     then 1
                     else 0
                end),
               (case when cast(tradetime as date) = cast(yyyymmddhh as date) and
                          datepart(hour, tradetime) = datepart(hour, yyyymddhh)
                     then tradetime
                end) asc,
               tradetime desc
    ) opening outer apply
    (select top 1 t.*
      from t
      where tradetime < dateadd(hour, 1, yyyymmddhh)
      order by (case when cast(tradetime as date) = cast(yyyymmddhh as date) and
                          datepart(hour, tradetime) = datepart(hour, yyyymddhh)
                     then 1
                     else 0
                end),
               tradetime desc
    ) closing;

我们的想法是在每个不同的小时内查询分钟的最小值和最大值,然后查询分钟1和分钟60的相关价格,以便获得开盘价和收盘价。

我希望这可以帮助您继续解决您的问题,或者至少给您一个可能的解决方案的暗示。

最好的祝愿,

女士。

© www.soinside.com 2019 - 2024. All rights reserved.