Điền vào các ngày bị thiếu với giá trị dữ liệu từ ngày được điền trước đó cho nhóm


13

Hình ảnh vé bàn trợ giúp được chuyển giữa các bộ phận. Chúng tôi muốn biết bộ phận này là gì vào cuối ngày cho mỗi vé cho mỗi ngày mà vé được mở. Bảng chứa bộ phận cuối cùng cho mỗi vé cho mỗi ngày nó được mở trên đó có sự thay đổi trong bộ phận (bao gồm một hàng cho ngày mà vé ban đầu được mở và ngày được đóng). Bảng dữ liệu trông như thế này:

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

Những gì tôi cần là điền vào bất kỳ ngày bị thiếu nào cho mỗi TicketId, bằng cách sử dụng DepartmentId từ hàng TicketAssigment trước đó được sắp xếp theo Ngày.

Nếu tôi có các hàng TicketAssigment như thế này:

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

Tôi muốn đầu ra này:

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

Điều này có vẻ như có thể gần với những gì tôi cần, nhưng tôi không đủ kiên nhẫn để hoàn thành và chi phí kế hoạch ước tính có 6 chữ số:

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;

Tôi nghi ngờ có một cách để làm điều này bằng cách sử dụng LAG và khung cửa sổ, nhưng tôi vẫn chưa tìm ra. Một cách hiệu quả hơn để đáp ứng yêu cầu là gì?

Câu trả lời:


14

Sử dụng LEAD()để có được hàng tiếp theo trong phân vùng TicketId. Sau đó tham gia vào bảng Lịch để có được tất cả các ngày giữa.

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)
;

Tất cả các cách để có được bảng Lịch ...


4

Đây là một cách làm nhanh chóng (Tôi chưa thử nghiệm về hiệu suất hoặc khả năng mở rộng)

- tạo bảng Lịch

-- 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;

--- tạo bảng thử nghiệm của bạn

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  )

--- Truy vấn để có đầu ra mong muốn

;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

nhập mô tả hình ảnh ở đây


Cảm ơn vì điều đó! Kế hoạch thực hiện ước tính cho thấy một tập hợp kết quả gồm 25 tỷ hàng, vì vậy chúng tôi sẽ đàm phán lại yêu cầu báo cáo (hiện đang báo cáo mỗi ngày cho mỗi vé trong năm qua). Tôi hy vọng chúng tôi có thể hiển thị Bộ cuối cùng cho mỗi vé và hiển thị chi tiết của Bộ theo từng ngày cho một vé được chọn theo yêu cầu.
Đánh dấu Freeman
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.