แทรกวันที่หายไปจากแบบสอบถาม


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

โปรดทราบว่าฉันได้เข้าถึงเซิร์ฟเวอร์เท่านั้น


คุณใช้แบบสอบถามเพื่อดึงผลลัพธ์หรือไม่ หรือคุณกำหนดช่วงวันที่ไว้ คุณสามารถเพิ่ม
คิวรี

1
ใช้ตารางปฏิทินเลือกจากนั้นเข้าร่วมความถี่ของคุณตามวันที่social.technet.microsoft.com/wiki/contents/articles/ …
ทำเครื่องหมาย Sinkinson

ฉันใช้คิวรีเพื่อดึงผลลัพธ์จากตารางหลัก
Arvin

หากคุณมีการเข้าถึงแบบอ่านอย่างเดียวคุณไม่ควรแทรกหรืออัพเดทฐานข้อมูล ขอให้ทีม DBA ช่วยคุณแทน
Kin Shah

1
@ คินฉันคิดว่าคำถามหมายความว่าพวกเขาต้องการแทรกแถวในชุดผลลัพธ์แทนที่จะแทรกแถวลงในตารางฐานข้อมูลจริง
Mark Sinkinson

คำตอบ:


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

ซอ

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 มีราคาแพงกว่าแบบทวีคูณเนื่องจากช่วงวันที่กว้างขึ้น มีวิธีที่มีประสิทธิภาพมากกว่าในการหาเซตสำหรับจุดประสงค์นี้
Aaron Bertrand

@AaronBertrand ช่วงนี้ค่อนข้างเล็ก แต่มีลิงค์สำหรับทางเลือกสำหรับความอยากรู้ของฉัน
Mihai

1
ใช่นี่มันเป็นช่วงเล็ก ๆ ปัญหาคือคนเรียนรู้วิธีการนี้แล้วนำไปใช้ในระดับที่ใหญ่กว่าซึ่งมันจะกลายเป็นปัญหา เหตุใดจึงต้องใช้วิธีการที่ช้าเนื่องจากเป็น "ตกลง" ในกรณีนี้ ดูคำตอบของฉัน
Aaron Bertrand
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.