현재 허용 대답은 최고의 답변입니다,하지만 난 이유를 설명의 충분한 일을 생각하지 않습니다. 다른 대답은 분명히 한 눈에 훨씬 더 깔끔해 보이지만 (그 못생긴 사례 진술을 작성하려는 경우) 규모에서 운영을 시작할 때 훨씬 더 나빠질 수 있습니다.
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: )
여기에 내가 모든 것을 설정하는 방법이 있습니다
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;
내 시스템에서 이것은 테이블에 12,872,738 개의 행을 가져옵니다. 위의 각 쿼리를 시도하면 ( SELECT INTO
SSMS로 결과 인쇄를 마칠 때까지 기다릴 필요가 없으므로) 다음과 같은 결과가 나타납니다.
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%
쿼리 계획을 보면 왜 피벗 또는 집계 (또는 천국 금지 STRING_SPLIT
)를 추가하면 필요하지 않은 모든 종류의 추가 연산자 가 생길 수 있습니다. 병렬로 이동하여 다른 쿼리가 원하는 리소스를 제거하십시오). 계약에 따라 CASE
기반 솔루션은 병렬화되지 않고 매우 빠르게 실행되며 매우 간단합니다.
이 경우 무제한 리소스가없는 경우 (아직없는 경우) 가장 간단하고 빠른 방법을 선택해야합니다.
새 열을 계속 추가하고 사례 설명을 확장해야하는 경우 수행 할 작업에 대한 질문이있었습니다. 예, 이것은 다루기 힘들지만 다른 모든 솔루션도 마찬가지입니다. 이것이 실제로 그럴듯한 워크 플로라면 테이블을 다시 디자인해야합니다. 원하는 것은 아마도 다음과 같습니다.
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;
이것은 잠재적 인 성능 문제가 아니며 신중한 인덱스 튜닝이 필요하지만 임의의 수의 잠재적 타임 스탬프를 처리하는 가장 좋은 방법입니다
답변이 삭제 된 경우 여기에 내가 비교 한 버전이 있습니다 (순서대로)
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