Eksik tarihleri ​​grup için önceki doldurulmuş tarihten veri değeriyle doldurun


13

Bölümler arasında aktarılan resim yardım masası biletleri. Biletin açık olduğu her gün için her bir bilet için günün sonunda bölümün ne olduğunu bilmek istiyoruz. Tabloda, açık olduğu her gün için her bir biletin son bölümü, bölümde bir değişiklik olduğu (biletin ilk açıldığı tarih ve kapatıldığı tarih için bir satır dahil) bulunur. Veri tablosu şöyle görünür:

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

Ne ihtiyacım var her TicketId eksik tarih doldurmak için tarihe göre sipariş önceki TicketAssigment satır DepartmentId kullanarak.

Eğer böyle TicketAssigment satır varsa:

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

Bu çıktıyı istiyorum:

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

Bu, ihtiyacım olan şeye yakın olabilir, ancak bitmesine izin vermek için sabrım olmadı ve tahmini plan maliyetinin 6 hanesi var:

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 ve bir pencere çerçevesi kullanarak bunu yapmanın bir yolu olduğundan şüpheleniyorum, ama tam olarak anlayamadım. İhtiyacı karşılamanın daha etkili bir yolu nedir?

Yanıtlar:


14

LEAD()TicketId bölümündeki bir sonraki satırı almak için kullanın . Ardından, arasındaki tüm tarihleri ​​almak için bir Takvim tablosuna katılın.

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

Takvim tablosu almanın her türlü yolu ...


4

Bu yapmanın hızlı bir yoludur (Performans veya ölçeklenebilirlik açısından test etmedim)

- Takvim tablosu oluştur

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

--- test masanızı oluşturun

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  )

--- İstenilen çıktıyı almak için sorgu

;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

resim açıklamasını buraya girin


Bunun için teşekkürler! Tahmini yürütme planı, 25 milyar satırlık bir sonuç kümesini gösterir, bu nedenle (şu anda geçen yıl için her bilet için her gün rapor verecek olan) raporlama gereksinimini yeniden tartışacağız. Her bir bilet için son DepartmentId'i gösterebilir ve istek üzerine tek bir seçilen bilet için DepartmentId ayrıntılarını her gün gösterebiliriz.
Mark Freeman
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.