Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何用静态数据填充sql中缺少的行?_Sql_Sql Server - Fatal编程技术网

如何用静态数据填充sql中缺少的行?

如何用静态数据填充sql中缺少的行?,sql,sql-server,Sql,Sql Server,我收集了数周内一些证券的一分钟“滴答”股价数据,并将其存储在一个名为“日内”的表格中。此表包括每个交易日08:01:00至16:30:00之间的一分钟刻度数据 有些证券并不是每天每分钟都在交易,当它们不交易时,不会产生任何缺少刻度的行。我希望为所有缺失的滴答声插入行,这些滴答声的交易量为“0”,将从上一个股价带入整个股价 例如,目前,对于一种安全性,我存储了以下内容: ticker date tick cls vo

我收集了数周内一些证券的一分钟“滴答”股价数据,并将其存储在一个名为“日内”的表格中。此表包括每个交易日08:01:00至16:30:00之间的一分钟刻度数据

有些证券并不是每天每分钟都在交易,当它们不交易时,不会产生任何缺少刻度的行。我希望为所有缺失的滴答声插入行,这些滴答声的交易量为“0”,将从上一个股价带入整个股价

例如,目前,对于一种安全性,我存储了以下内容:

ticker     date           tick                     cls        volume

ASC        20151231       1899-12-30 12:30:00      3453       2743
ASC        20151231       1899-12-30 12:29:00      3449       3490
ASC        20151231       1899-12-30 12:28:00      3436       930
ASC        20151231       1899-12-30 12:27:00      3435       255
ASC        20151231       1899-12-30 12:26:00      3434       4
ASC        20151231       1899-12-30 12:23:00      3444.59    54
为每一个勾号的1899-12-30的恼人的日期道歉-这些使它看起来有点凌乱,但没有什么害处,因此为什么它们现在仍然存在

理想情况下,我希望存储的是:

ticker     date           tick                     cls        volume

ASC        20151231       1899-12-30 12:30:00      3453       2743
ASC        20151231       1899-12-30 12:29:00      3449       3490
ASC        20151231       1899-12-30 12:28:00      3436       930
ASC        20151231       1899-12-30 12:27:00      3435       255
ASC        20151231       1899-12-30 12:26:00      3434       4
ASC        20151231       1899-12-30 12:25:00      3444.59    0          < new row
ASC        20151231       1899-12-30 12:24:00      3444.59    0          < new row
ASC        20151231       1899-12-30 12:23:00      3444.59    54
因此,对于每个不同的股票代码和日期值,在08:01:00和16:30:00之间每分钟都有一个值范围。有些将与当前存储的相同,而另一些将具有0的体积图和复制上一个关闭值的关闭值

我完全被难住了,如果您能在这方面提供任何帮助,我将不胜感激


亲切的问候

使用递归CTE为所需范围创建时间表。我刚刚用了12分钟的时间使用了你样本中的数据,但你可以扩展它。在不使用光标的情况下获取最后一个非null值有点棘手,但这是可能的。如果你有兴趣的话,我会给你一个更全面的解释

下面的代码演示:

设置:

查询:


告诉我这是否有效。我使用了您提供的示例数据,它处理了缺少的行。这可能需要一点时间,这取决于你有多少记录。我创建了临时表来进行测试。您可能需要为每个股票代码符号执行一次

CREATE TABLE #Stocks (  ticker VARCHAR(5),
                    date DATE,
                    tick datetime,
                    cls money,
                    volume money)

INSERT INTO #Stocks (ticker, date, tick, cls, volume)
VALUES
('ASC','2015-12-31','1899-12-30 12:30:00',3453,2743),
('ASC','2015-12-31','1899-12-30 12:29:00',3449,3490),
('ASC','2015-12-31','1899-12-30 12:28:00',3436,930),
('ASC','2015-12-31','1899-12-30 12:27:00',3435,255),
('ASC','2015-12-31','1899-12-30 12:26:00',3434,4),
('ASC','2015-12-31','1899-12-30 12:23:00',3444.59,54)



DECLARE @TotalRows1 INT
SELECT @TotalRows1 = COUNT(*) FROM #Stocks
DECLARE @Row INT = 1
WHILE @Row < @TotalRows1
BEGIN
DECLARE @TotalRows INT
SELECT @TotalRows = COUNT(*) FROM #Stocks
 IF (SELECT DATEADD(MI,1,tick) FROM (SELECT ROW_NUMBER() OVER (ORDER BY tick) RowNumber, * FROM #Stocks) AS T1 WHERE T1.RowNumber = @Row)
<>
(SELECT T2.tick FROM (SELECT ROW_NUMBER() OVER (ORDER BY tick) RowNumber, * FROM #Stocks) AS T2 WHERE T2.RowNumber = @Row + 1)
BEGIN
INSERT INTO #Stocks
SELECT T.ticker, T.Date, DATEADD(MI,1,T.tick) tick, T.cls, 0.00
    FROM (SELECT ROW_NUMBER() OVER (ORDER BY tick) RowNumber, * FROM #Stocks) AS T
    WHERE T.RowNumber = @Row
SET @Row = @Row +1
END
ELSE
SET @Row = @Row +1
END

SELECT *
FROM #Stocks
ORDER BY tick DESC

令人沮丧的是,我忘了在第一个表中提到,在12:25:00和12:24:00时没有股票代码“ASC”的交易,因此没有这些值的记录……我想输入的是这些值。希望这在我的第二张表中很明显,但只是为了进一步澄清。非常感谢。你现在需要立即这样做来填补数据库的空白,还是将来也需要这样做呢?嗨,德克辛-一次完成。我已经完成了数据的收集,现在我需要对所有数据进行历史检查并添加值。一次,您可以创建一个光标来检查数据,并在缺少数据时插入。或者创建一个每分钟填充0个值的虚拟表,并将虚拟表中缺少的数据插入到实际表中。或者联合/加入虚拟表和真实表。谢谢你花时间回答这个问题,德克辛。如果我创建一个虚拟表,这是否允许我将数据插入到每个缺少的行中,对于每个安全性,我都有几百个“ticker”代码,我需要这样做?此外,如果没有“cls”价格,是否允许我复制之前的“cls”价格。如果在所有字段中插入0值,我可以看到这样做的好处,但在这种情况下,“cls”价格将取决于之前的“cls”。在这种情况下,这种方法有效吗?谢谢。你的演示非常出色。当我尝试在SQL Server中使用完整数据集运行此操作时,我收到以下消息:“Msg 402,级别16,状态1,第21行,数据类型datetime和time在等于运算符中不兼容”。将“time”更改为“datetime”会导致此错误消息消失,但结果是510行空白数据,而不是08:01:00到16:30:00之间的分钟刻度。这似乎是SQL Server 2008/2012转换中的一个错误,因此我将对此进行研究,但如果您知道任何快速修复方法,可能会出现空白行,这可能是因为表中的刻度值与cte中的TM值不匹配。由于已将其更新为日期时间,请验证每个中的日期部分是否正确匹配。你们也可以在时间上打钩,因为日期似乎不需要。也可以认为这一次只对一个代码值有效。不确定您是否正在尝试使用多个?更新了上面的答案。如果您希望能够一次性处理所有的标记,并将所有数据(包括缺少的标记)插入新的表test_data2,则必须循环遍历数据。还更新了TM to datetime的格式,使其与您的表一致。使用1899-12-30作为样本数据中的日期部分。感谢您的帮助。因此,在这种情况下,我可以将每个股票代码的数据一个接一个地输入临时表,从advfn.dbo.intraday中选择ticker、date、tick、cls、volume进入test.dbo.test_stocks,其中ticker='ASC',运行上面的查询并将行插入组合数据库,删除临时表,然后对下一个股票代码执行相同的过程?这将适合…虽然有大约1000个股票代码,所以需要几个小时-bu 它不会比手工操作快很多很多!谢谢你的帮助。
Declare @tickers Table (ticker varchar(5));
Insert into @tickers select distinct ticker from test_data;

Declare @ticker varchar(5);
While exists (Select * From @tickers)
  BEGIN
    select @ticker = min(ticker) from @tickers;

    with cte(tm) 
    as( Select cast('1899-12-30 12:23:00' as datetime) as tm
        union all
    Select dateadd(minute, 1, tm)
        from cte
        where tm < cast('1899-12-30 12:31:00' as datetime)
    )    

    insert into test_data2 
    select 
      max(ticker) over (partition by grp order by tick rows unbounded preceding) ticker,
      max(date) over (partition by grp order by tick rows unbounded preceding) date,
      tick,
      max(cls) over (partition by grp order by tick rows unbounded preceding) cls,
      volume
    from (
          select
              ticker,
              date,
              tick,
              cls,
              volume,
              id,
              max(id1) OVER(ORDER BY tick ROWS UNBOUNDED PRECEDING) AS grp
          from (
                select 
                  td.ticker,
                  td.date,
                  coalesce(td.tick, cte.tm) tick,
                  td.cls,
                  coalesce(td.volume, 0) volume,
                  row_number() over (order by tick) id
                from test_data td
                right outer join cte
                on td.tick = cte.tm
                and td.ticker = @ticker
         ) cte2
         CROSS APPLY ( VALUES( CASE WHEN ticker IS NOT NULL THEN id END) )
            AS A(id1)
     ) cte3;

      Delete from @tickers where ticker = @ticker;
    End

select * from test_data2
order by ticker, tick;
CREATE TABLE #Stocks (  ticker VARCHAR(5),
                    date DATE,
                    tick datetime,
                    cls money,
                    volume money)

INSERT INTO #Stocks (ticker, date, tick, cls, volume)
VALUES
('ASC','2015-12-31','1899-12-30 12:30:00',3453,2743),
('ASC','2015-12-31','1899-12-30 12:29:00',3449,3490),
('ASC','2015-12-31','1899-12-30 12:28:00',3436,930),
('ASC','2015-12-31','1899-12-30 12:27:00',3435,255),
('ASC','2015-12-31','1899-12-30 12:26:00',3434,4),
('ASC','2015-12-31','1899-12-30 12:23:00',3444.59,54)



DECLARE @TotalRows1 INT
SELECT @TotalRows1 = COUNT(*) FROM #Stocks
DECLARE @Row INT = 1
WHILE @Row < @TotalRows1
BEGIN
DECLARE @TotalRows INT
SELECT @TotalRows = COUNT(*) FROM #Stocks
 IF (SELECT DATEADD(MI,1,tick) FROM (SELECT ROW_NUMBER() OVER (ORDER BY tick) RowNumber, * FROM #Stocks) AS T1 WHERE T1.RowNumber = @Row)
<>
(SELECT T2.tick FROM (SELECT ROW_NUMBER() OVER (ORDER BY tick) RowNumber, * FROM #Stocks) AS T2 WHERE T2.RowNumber = @Row + 1)
BEGIN
INSERT INTO #Stocks
SELECT T.ticker, T.Date, DATEADD(MI,1,T.tick) tick, T.cls, 0.00
    FROM (SELECT ROW_NUMBER() OVER (ORDER BY tick) RowNumber, * FROM #Stocks) AS T
    WHERE T.RowNumber = @Row
SET @Row = @Row +1
END
ELSE
SET @Row = @Row +1
END

SELECT *
FROM #Stocks
ORDER BY tick DESC