Die derzeit akzeptierte Antwort ist die beste Antwort, aber ich denke nicht, dass sie gut genug ist, um zu erklären, warum. Die anderen Antworten sehen auf den ersten Blick sicherlich viel sauberer aus (wer möchte diese hässliche Fallerklärung schreiben), sind aber wahrscheinlich viel schlechter, wenn Sie anfangen, in großem Maßstab zu arbeiten.
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: )
So richte ich alles ein
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;
Auf meinem System werden dadurch 12.872.738 Zeilen in der Tabelle angezeigt. Wenn ich jede der oben genannten Abfragen versuche (angepasst, SELECT INTO
damit ich nicht warten muss, bis der Druck der Ergebnisse in SSMS abgeschlossen ist), erhalte ich die folgenden Ergebnisse:
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%
Wenn Sie sich die Abfragepläne ansehen, wird es ziemlich offensichtlich, warum - wenn Sie irgendeine Art von Unpivot oder Aggregat hinzufügen (oder der Himmel verbietet STRING_SPLIT
), erhalten Sie alle möglichen zusätzlichen Operatoren, die Sie nicht benötigen (und das zwingt den Plan dazu Gehen Sie parallel und nehmen Sie Ressourcen weg, die andere Abfragen möglicherweise benötigen. Laut Vertrag CASE
läuft die basierte Lösung nicht parallel, läuft sehr schnell und ist unglaublich einfach.
In diesem Fall sollten Sie den einfachsten und schnellsten Ansatz wählen, es sei denn, Sie verfügen über unbegrenzte Ressourcen (Sie haben keine).
Es stellte sich die Frage, was zu tun ist, wenn Sie ständig neue Spalten hinzufügen und die case-Anweisung erweitern müssen. Ja, das wird unhandlich, aber jede andere Lösung auch. Wenn dies tatsächlich ein plausibler Workflow ist, sollten Sie Ihre Tabelle neu gestalten. Was Sie wollen, sieht wahrscheinlich ungefähr so aus:
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;
Dies ist sicherlich nicht frei von potenziellen Leistungsproblemen und erfordert eine sorgfältige Indexoptimierung, ist jedoch der beste Weg, um mit einer beliebigen Anzahl potenzieller Zeitstempel umzugehen
Falls irgendwelche Antworten gelöscht werden, hier sind die Versionen, die ich verglichen habe (in der Reihenfolge)
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