クエリから欠落している日付を挿入する


9

作成したクエリから欠落している日付を挿入するにはどうすればよいですか?以下の結果:

Date          Frequency
2014-05-18    5
2014-05-20    7
2014-05-25    7
2014-05-27    6

以下に示すように、結果に日付が0の欠落したい場合:

Date          Frequency
2014-05-18    5
2014-05-19    0
2014-05-20    7
2014-05-21    0
2014-05-22    0
2014-05-23    0
2014-05-24    0
2014-05-25    7
2014-05-26    0
2014-05-27    6

私はサーバーへの読み取り専用アクセスを持っていることに注意してください。


結果を取得するためにクエリを使用していますか?または、日付範囲が定義されていますか。あなたのクエリまたはテーブルを追加することができます
vijayp

1
、カレンダーのテーブルを使用していることから選択し、日付で、あなたの周波数に参加social.technet.microsoft.com/wiki/contents/articles/...
マーク・Sinkinson

クエリを使用して、メインテーブルから結果をフェッチしています。
Arvin

読み取り専用アクセス権がある場合、データベースを挿入または更新することは想定されていません。代わりに、DBAチームに支援を依頼してください。
Kin Shah

1
@Kin質問は、実際のデータベーステーブルに行を挿入するのではなく、結果セットに行を挿入することを望んでいると思います。
Mark Sinkinson、2014

回答:


12

これは、カレンダーテーブルを使用した例です(実際に使用する必要があります)。この例では2014年のデータを入力していますが、何年でも好きなだけ詰め込むことができます...

CREATE TABLE dbo.Calendar(d DATE PRIMARY KEY);

INSERT dbo.Calendar(d) SELECT TOP (365)
 DATEADD(DAY, ROW_NUMBER() OVER (ORDER BY number)-1, '20140101')
 FROM [master].dbo.spt_values
 WHERE [type] = N'P' ORDER BY number;

これでクエリは簡単です。

DECLARE @s DATE = '20140518', @e DATE = '20140527';

SELECT c.d, Frequency = COALESCE(s.Frequency,0)
  FROM dbo.Calendar AS c
  LEFT OUTER JOIN dbo.splunge AS s
  ON c.d = s.[date]
  WHERE c.d >= @s
    AND c.d < DATEADD(DAY, 1, @e);

SQLfiddleの例

カレンダーテーブルを作成できない場合(および便利な数字テーブルがない場合)、インラインで配置できます。

DECLARE @s DATE = '20140518', @e DATE = '20140527';

SELECT c.d, Frequency = COALESCE(s.Frequency,0)
  FROM 
(
   SELECT TOP (DATEDIFF(DAY, @s, @e)+1)
 DATEADD(DAY, ROW_NUMBER() OVER (ORDER BY number)-1, @s)
 FROM [master].dbo.spt_values
 WHERE [type] = N'P' ORDER BY number
) AS c(d)
  LEFT OUTER JOIN dbo.splunge2 AS s
  ON c.d = s.[date]
  WHERE c.d >= @s
    AND c.d < DATEADD(DAY, 1, @e);

SQLfiddleの例

(日付、数値などの)セットの生成の詳細については、次のシリーズを参照してください。


0
DECLARE @t TABLE(Dt Date,Frequency int)
INSERT INTO @t VALUES
('2014-05-18',5),('2014-05-20',7),('2014-05-25',7),('2014-05-27',6)



DECLARE @startDate DATE, @endDate DATE
SELECT @startDate = '2014-05-18', @endDate = '2014-05-27' --yyyy-mm-dd
;WITH Calender AS (
    SELECT @startDate AS CalanderDate
    UNION ALL
    SELECT DATEADD(day,1,CalanderDate) FROM Calender
    WHERE DATEADD(day,1,CalanderDate) <= @endDate
)
INSERT INTO @t SELECT
    Dt = CalanderDate,Frequency = 0

FROM Calender c
LEFT JOIN @t t 
ON t.Dt = c.CalanderDate
WHERE t.dt IS NULL
option (maxrecursion 0)

SELECT * FROM @t ORDER BY dt

FIDDLE

2014-05-18  5
2014-05-19  0
2014-05-20  7
2014-05-21  0
2014-05-22  0
2014-05-23  0
2014-05-24  0
2014-05-25  7
2014-05-26  0
2014-05-27  6

日付範囲が広くなると、再帰CTEアプローチは指数関数的に高くなります。この目的のためのセットを導出するためのより効率的な方法があります。
アーロンバートランド

@AaronBertrand範囲はここではかなり小さいですが、代替案へのリンクはありますか?
Mihai 2014

1
はい、ここでは、たまたま狭い範囲です。問題は、人々がこのアプローチを学び、それが問題になるはるかに大きなスケールで適用することです。この場合に「大丈夫」であるという理由だけで、スローアプローチを使用する理由は何ですか。私の答えを見てください。
アーロンバートランド
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.