Şu anda kabul edilen cevap en iyi cevaptır, ancak bunun nedenini açıklamak için yeterince iyi bir iş yaptığını düşünmüyorum. Diğer cevaplar kesinlikle bir bakışta daha temiz görünüyor (bu çirkin vaka ifadesini yazmak isteyen), ancak ölçekli çalışmaya başladığınızda çok daha kötü olacak gibi görünüyor.
SELECT @@VERSION
Microsoft SQL Server 2016 (SP2) (KB4052908) - 13.0.5026.0 (X64)
Mar 18 2018 09:11:49
Copyright (c) Microsoft Corporation
Developer Edition (64-bit) on Windows 10 Enterprise 10.0 <X64> (Build 17763: )
İşte her şeyi nasıl ayarladım
DECLARE @Offset bigint = 0;
DECLARE @Max bigint = 10000000;
DROP TABLE IF EXISTS #Indebtedness;
CREATE TABLE #Indebtedness
(
call_case char(10) COLLATE DATABASE_DEFAULT NOT NULL,
date1 datetime NULL,
date2 datetime NULL,
date3 datetime NULL
);
WHILE @Offset < @Max
BEGIN
INSERT INTO #Indebtedness
( call_case, date1, date2, date3 )
SELECT @Offset + ROW_NUMBER() OVER ( ORDER BY ( SELECT NULL )),
DATEADD( DAY,
CASE WHEN RAND() > 0 THEN 1
ELSE -1 END * ROUND( RAND(), 0 ),
CURRENT_TIMESTAMP ),
DATEADD( DAY,
CASE WHEN RAND() > 0 THEN 1
ELSE -1 END * ROUND( RAND(), 0 ),
CURRENT_TIMESTAMP ),
DATEADD( DAY,
CASE WHEN RAND() > 0 THEN 1
ELSE -1 END * ROUND( RAND(), 0 ),
CURRENT_TIMESTAMP )
FROM master.dbo.spt_values a
CROSS APPLY master.dbo.spt_values b;
SET @Offset = @Offset + ROWCOUNT_BIG();
END;
Sistemimde bu bana tabloda 12.872.738 satır alıyor. Yukarıdaki sorguların her birini denerseniz ( SELECT INTO
böylece SSMS sonuçları yazdırmayı bitirmek için beklemek gerekmez için tweaked ), aşağıdaki sonuçları elde:
Method | CPU time (ms) | Elapsed time (ms) | Relative Cost
-----------------------------------------------------------------------------------------
Tim Biegeleisen (CASE) | 13485 | 2167 | 2%
Red Devil (Subquery over MAX columns) | 55187 | 9891 | 14%
Vignesh Kumar (Subquery over columns) | 33750 | 5139 | 5%
Serkan Arslan (UNPIVOT) | 86205 | 15023 | 12%
Metal (STRING_SPLIT) | 459668 | 186742 | 68%
Sorgu planlarına bakarsanız, neden oldukça açık hale gelir - herhangi bir unpivot veya agrega (veya cennet yasak STRING_SPLIT
) ekleyerek ihtiyacınız olmayan her türlü ek işleçle karşılaşırsınız (ve planı diğer sorguların isteyebileceği kaynakları alıp paralellik gösterir). Sözleşmeyle, CASE
temel çözüm paralel gitmez, çok hızlı çalışır ve inanılmaz derecede basittir.
Bu durumda, sınırsız kaynağınız yoksa (yoksa), en basit ve en hızlı yaklaşımı seçmelisiniz.
Yeni sütunlar eklemeye ve vaka ifadesini genişletmeye devam etmeniz gerekiyorsa ne yapılacağı sorusu vardı. Evet, bu zorlaşıyor, ama diğer tüm çözümler de öyle. Bu aslında makul bir iş akışı ise, tablonuzu yeniden tasarlamanız gerekir. İstediğiniz şey muhtemelen şöyle görünür:
CREATE TABLE #Indebtedness2
(
call_case char(10) COLLATE DATABASE_DEFAULT NOT NULL,
activity_type bigint NOT NULL, -- This indicates which date# column it was, if you care
timestamp datetime NOT NULL
);
SELECT Indebtedness.call_case,
Indebtedness.activity_type,
Indebtedness.timestamp
FROM ( SELECT call_case,
activity_type,
timestamp,
ROW_NUMBER() OVER ( PARTITION BY call_case
ORDER BY timestamp DESC ) RowNumber
FROM #Indebtedness2 ) Indebtedness
WHERE Indebtedness.RowNumber = 1;
Bu kesinlikle potansiyel performans sorunlarından bağımsız değildir ve dikkatli bir indeks ayarlaması gerektirir, ancak keyfi sayıda potansiyel zaman damgasıyla başa çıkmanın en iyi yoludur.
Herhangi bir yanıtın silinmesi durumunda, karşılaştırdığım sürümler (sırayla)
SELECT
call_case,
CASE WHEN date1 > date2 AND date1 > date3
THEN date1
WHEN date2 > date3
THEN date2
ELSE date3 END AS [Latest Date]
FROM #indebtedness;
SELECT call_case,
(SELECT Max(v)
FROM (VALUES (date1), (date2), (date3),...) AS value(v)) as [MostRecentDate]
FROM #indebtedness
SELECT call_case,
(SELECT
MAX(call_case)
FROM ( VALUES
(MAX(date1)),
(MAX(date2))
,(max(date3))
) MyAlias(call_case)
)
FROM #indebtedness
group by call_case
select call_case, MAX(date) [Latest Date] from #indebtedness
UNPIVOT(date FOR col IN ([date1], [date2], [date3])) UNPVT
GROUP BY call_case
select call_case , max(cast(x.Item as date)) as 'Latest Date' from #indebtedness t
cross apply dbo.SplitString(concat(date1, ',', date2, ',', date3), ',') x
group by call_case