web-dev-qa-db-ja.com

クエリを介してSQLの日付列にループを追加する方法

ID = 01234そして、このIDは次のように1か月に3回のトランザクションを実行しました。

***DAY_no              Balance*** 
   1/1/2018              5000
   10/1/2018             10000
   15/1/2018             12000

私はこれらのデータをこのようにしたいです:

***DAY_no              Balance*** 
   1/1/2018              5000
   2/1/2018              5000
   3/1/2018              5000
   4/1/2018              5000
   5/1/2018              5000
   6/1/2018              5000
   7/1/2018              5000
   8/1/2018              5000
   9/1/2018              5000
   10/1/2018             10000
   11/1/2018             10000
   12/1/2018             10000
   13/1/2018             10000
   14/1/2018             10000
   15/1/2018             12000
   16/1/2018             12000
   17/1/2018             12000
   18/1/2018             12000
   19/1/2018             12000
   20/1/2018             12000
   21/1/2018             12000
   22/1/2018             12000
   23/1/2018             12000
   24/1/2018             12000
   25/1/2018             12000
   26/1/2018             12000
   27/1/2018             12000
   28/1/2018             12000
   29/1/2018             12000
   30/1/2018             12000
   31/1/2018             12000
1
hassy_has

カレンダーテーブルを使用できます。

CREATE TABLE Calendar(cDate datetime, cDay int, cDayOfWeek int, cDayName varchar(20), cMonth int);

DECLARE @date date = '20180101';
WHILE @date <= '20180131'
BEGIN
    INSERT INTO Calendar VALUES (@date, 
                                 DAY(@date), 
                                 DATEPART(weekday, @date), 
                                 DATENAME(weekday, @date),
                                 MONTH (@date));
    SET @date = DATEADD(day, 1, @date);
END


CREATE TABLE Mov (Day_no date, Balance int);
INSERT INTO Mov VALUES
('20180101', 5000),
('20180110', 10000),
('20180115', 12000);
GO
 34行が影響を受けました
SELECT cDAte, (SELECT TOP 1 Balance
               FROM   Mov
               WHERE  Day_no <= cDate
               ORDER BY Day_no DESC) Balance
FROM   Calendar
WHERE cMonth = 1;
GO
 cDAte |バランス
:--------------- ------:
 2018/01/01 00:00:00 | 5000 
 2018年2月1日00:00:00 | 5000 
 2018年3月1日00:00:00 | 5000 
 2018/01/04 00:00:00 | 5000 
 2018年1月5日00:00:00 | 5000 
 2018年1月6日00:00:00 | 5000 
 2018年1月7日00:00:00 | 5000 
 2018年1月8日00:00:00 | 5000 
 2018年1月9日00:00:00 | 5000 
 2018年1月10日00:00:00 | 10000 
 2018年11月1日00:00:00 | 10000 
 2018年12月1日00:00:00 | 10000 
 2018年1月13日00:00:00 | 10000 
 2018/01/14 00:00:00 | 10000 
 2018/01/15 00:00:00 | 12000 
 2018/01/16 00:00:00 | 12000 
 2018年1月17日00:00:00 | 12000 
 2018/01/18 00:00:00 | 12000 
 2018年1月19日00:00:00 | 12000 
 2018年1月20日00:00:00 | 12000 
 2018年1月21日00:00:00 | 12000 
 2018年1月22日00:00:00 | 12000 
 2018年1月23日00:00:00 | 12000 
 2018年1月24日00:00:00 | 12000 
 2018年1月25日00:00:00 | 12000 
 2018年1月26日00:00:00 | 12000 
 2018年1月27日00:00:00 | 12000 
 2018/01/28 00:00:00 | 12000 
 2018年1月29日00:00:00 | 12000 
 2018/01/30 00:00:00 | 12000 
 2018年1月31日00:00:00 | 12000 

dbfiddle ---(ここ

6
McNets

この種の問題を解決するには、常にカレンダーテーブルを用意する必要があります(SQL Serverの何かを "ループ"と考えないようにしてください-セットで機能するように最適化されています)。

-- this produces all the days from 2000-01-01 through 2099-12-31
CREATE TABLE dbo.Calendar(d date PRIMARY KEY);

DECLARE @s date = '20000101', @e date = '20991231';

INSERT dbo.Calendar(d) 
  SELECT DATEADD(DAY, r-1, @s)
  FROM ( SELECT TOP (DATEDIFF(DAY, @s, @e)+1)
           r = ROW_NUMBER() OVER (ORDER BY o.[object_id]) 
         FROM sys.all_objects AS o
         CROSS JOIN sys.all_objects AS c
       ) AS x;

カレンダーテーブルを設定すると、クエリでLEFT JOINを使用して、このようなギャップを埋めることができます。このデータがあると仮定します:

CREATE TABLE #sample
(
  DAY_no  date, 
  Balance int
);

INSERT #sample(DAY_no,Balance)
VALUES('20180101', 5000 ),
      ('20180110', 10000),
      ('20180115', 12000);

クエリは次のとおりです(私は変数を使用して、あなたが次の月を定義しています):

DECLARE @month date = DATEFROMPARTS(2018,1,1);

SELECT DAY_no = c.d,
       MAX(s.Balance)
    FROM dbo.Calendar AS c
    LEFT OUTER JOIN #sample AS s
    ON s.DAY_no <= c.d
    WHERE c.d >= @month
      AND c.d <  DATEADD(MONTH, 1, @month)
    GROUP BY c.d
    ORDER BY c.d;

もちろん、前の月から最後の既知の残高を取得する必要があるため、最初のデータポイントがその月の1日より後の場合は、クエリをより複雑にする必要があります。

カレンダーテーブルの詳細については、 このヒント を参照してください。

6
Aaron Bertrand