กรอกข้อมูลวันที่ที่หายไปด้วยค่าข้อมูลจากวันที่ที่เติมก่อนหน้าสำหรับกลุ่ม


13

รูปภาพตั๋วโต๊ะช่วยเหลือที่รับถ่ายโอนระหว่างแผนกต่างๆ เราต้องการทราบว่าแผนกคืออะไรในตอนท้ายของวันสำหรับตั๋วแต่ละใบสำหรับแต่ละวันที่เปิดตั๋ว ตารางประกอบด้วยแผนกสุดท้ายสำหรับแต่ละตั๋วสำหรับแต่ละวันที่เปิดซึ่งมีการเปลี่ยนแปลงในแผนก (รวมถึงแถวสำหรับวันที่เปิดตั๋วในตอนแรกและวันที่ปิด) ตารางข้อมูลมีลักษณะดังนี้:

CREATE TABLE TicketAssigment (
    TicketId     INT NOT NULL,
    AssignedDate DATE NOT NULL,
    DepartmentId INT NOT NULL);

สิ่งที่ฉันต้องการคือการกรอกวันที่ที่ขาดหายไปสำหรับ TicketId แต่ละอันโดยใช้ DepartmentId จากแถว TicketAssigment หน้าที่แล้วเรียงลำดับตามวันที่

หากฉันมี TicketAssigment แถวเช่นนี้:

1, '1/1/2016', 123 -- Opened
1, '1,4,2016', 456 -- Transferred and closed
2, '1/1/2016', 25  -- Opened
2, '1/2/2016', 52  -- Transferred
2, '1/4/2016', 25  -- Transferred and closed

ฉันต้องการผลลัพธ์นี้:

1, '1/1/2016', 123
1, '1/2/2016', 123
1, '1/3/2016', 123
1, '1/4/2016', 456
2, '1/1/2016', 25
2, '1/2/2016', 52
2, '1/3/2016', 52
2, '1/4/2016', 25

ดูเหมือนว่ามันอาจจะใกล้เคียงกับสิ่งที่ฉันต้องการ แต่ฉันไม่มีความอดทนที่จะให้มันเสร็จสิ้นและค่าใช้จ่ายตามแผนโดยประมาณมี 6 หลัก:

SELECT  l.TicketId, c.Date, MIN(l.DepartmentId)
FROM    dbo.Calendar c 
        OUTER APPLY (SELECT TOP 1 TicketId, DepartmentId FROM TicketAssigment WHERE AssignedDate <= c.Date ORDER BY AssignedDate DESC) l
WHERE   c.Date <= (SELECT MAX(AssignedDate) FROM TicketAssigment)
GROUP   BY l.TicketId, c.Date
ORDER   BY l.TicketId, c.Date;

ฉันสงสัยว่ามีวิธีการทำเช่นนี้โดยใช้ LAG และกรอบหน้าต่าง แต่ฉันไม่ได้คิดออก วิธีที่มีประสิทธิภาพมากขึ้นในการตอบสนองความต้องการคืออะไร?

คำตอบ:


14

ใช้LEAD()เพื่อรับแถวถัดไปภายในพาร์ติชัน TicketId จากนั้นเข้าร่วมในตารางปฏิทินเพื่อรับวันที่ทั้งหมดระหว่าง

WITH TAwithnext AS
(SELECT *, LEAD(AssignmentDate) OVER (PARTITION BY TicketID ORDER BY AssignmentDate) AS NextAssignmentDate
 FROM TicketAssignment
)
SELECT t.TicketID, c.Date, t.DepartmentID
FROM dbo.Calendar c
JOIN TAwithnext t
    ON c.Date BETWEEN t.AssignmentDate AND ISNULL(DATEADD(day,-1,t.NextAssignmentDate),t.AssignmentDate)
;

วิธีต่างๆในการรับตารางปฏิทิน ...


4

นี่เป็นวิธีที่รวดเร็วในการทำ (ฉันไม่ได้ทดสอบประสิทธิภาพหรือความยืดหยุ่น)

- สร้างตารางปฏิทิน

-- borrowed from @Aaron's post http://sqlperformance.com/2013/01/t-sql-queries/generate-a-set-3 
CREATE TABLE dbo.Calendar(d DATE PRIMARY KEY);

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

--- สร้างตารางทดสอบของคุณ

CREATE TABLE dbo.TicketAssigment (
    TicketId     INT NOT NULL,
    AssignedDate DATE NOT NULL,
    DepartmentId INT NOT NULL);

--  truncate table dbo.TicketAssigment;

insert into dbo.TicketAssigment values (1   ,   '1-1-2016'  ,   123 )
insert into dbo.TicketAssigment values (1   ,   '1-4-2016'  ,   456 )
insert into dbo.TicketAssigment values (2   ,   '1-1-2016'  ,   25  )
insert into dbo.TicketAssigment values (2   ,   '1-2-2016'  ,   52  )
insert into dbo.TicketAssigment values (2   ,   '1-4-2016'  ,   25  )

--- แบบสอบถามเพื่อรับผลลัพธ์ที่ต้องการ

;with Cte as
(
  select TicketID, 
         min(AssignedDate) minAD, -- This is the min date
         max(AssignedDate) maxAD  -- This is the max date
  from TicketAssigment
  group by TicketID
)
select Cte.TicketID,
       c.d as AssignedDate,

       ( -- Get DeptID
       select top(1) T.departmentID
       from dbo.TicketAssigment as T
       where T.TicketID = cte.TicketID and
             T.AssignedDate <= c.d
       order by T.AssignedDate desc
       ) as DepartmentID
from Cte
  left outer join dbo.Calendar as c
      on c.d between Cte.minAD and Cte.maxAD
    order by Cte.TicketID

ป้อนคำอธิบายรูปภาพที่นี่


ขอบคุณสำหรับสิ่งนี้! แผนการดำเนินการโดยประมาณแสดงชุดผลลัพธ์จำนวน 25 พันล้านแถวดังนั้นเราจะเจรจาข้อกำหนดการรายงานใหม่ (ซึ่งปัจจุบันจะรายงานทุกวันสำหรับตั๋วทุกใบในปีที่ผ่านมา) ฉันหวังว่าเราจะสามารถแสดง DepartmentId ล่าสุดสำหรับแต่ละตั๋วและแสดงรายละเอียดของ DepartmentId ต่อวันสำหรับตั๋วที่เลือกไว้หนึ่งใบเมื่อมีการร้องขอ
Mark Freeman
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.