sql sql-server datetime

sql - Obtenga las Ășltimas fechas de varias columnas



sql-server datetime (5)

En mi opinión, Pivot es la mejor y más eficiente opción para esta consulta. Copie y pegue en el servidor MS SQL. Por favor revise el código escrito a continuación:

CREATE TABLE #indebtedness (call_case CHAR(10), date1 DATETIME, date2 DATETIME, date3 DATETIME) INSERT #indebtedness VALUES (''Key1'', ''2019-10-30'', ''2019-11-30'', ''2019-10-31'') INSERT #indebtedness VALUES (''Key2'', ''2019-10-20'', ''2019-10-30'', ''2019-11-21'') INSERT #indebtedness VALUES (''Key3'', ''2019-11-11'', ''2019-10-29'', ''2019-10-30'') INSERT #indebtedness VALUES (''Key4'', Null, ''2019-10-29'', ''2019-10-13'') --Solution-1: SELECT call_case, MAX(RecnetDate) as MaxDateColumn FROM #indebtedness UNPIVOT (RecnetDate FOR COL IN ([date1], [date2], [date3])) as TRANSPOSE GROUP BY call_case --Solution-2: select call_case, case when date1>date2 and date1 > date3 then date1 when date2>date3 then date2 when date3>date1 then date1 else date3 end as date from #indebtedness as a Drop table #indebtedness

Parece que debería ser fácil. ¿Cómo obtengo las últimas fechas que están en diferentes columnas?

DROP TABLE #indebtedness CREATE TABLE #indebtedness (call_case CHAR(10), date1 DATETIME, date2 DATETIME, date3 DATETIME) INSERT #indebtedness VALUES (''Key1'', ''2019-10-30'', ''2019-11-30'', ''2019-10-25'') INSERT #indebtedness VALUES (''Key2'', ''2019-10-20'', ''2019-10-30'', ''2019-10-15'') INSERT #indebtedness VALUES (''Key3'', ''2019-11-11'', ''2019-10-29'', ''2019-10-30'') INSERT #indebtedness VALUES (''Key4'', null , ''2019-10-29'', ''2019-10-13'') select call_case, ?? AS ''Latest Date'' from #indebtedness

Me gustaría que el resultado sea:

call_case Latest Date Key1 2019-11-30 Key2 2019-10-30 Key3 2019-11-11 Key4 2019-10-29


La respuesta actualmente aceptada es la mejor respuesta, pero no creo que explique por qué. Las otras respuestas ciertamente se ven mucho más limpias de un vistazo (quién quiere escribir esa fea declaración de caso), pero es probable que sean mucho peores cuando comience a operar a escala.

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

Así es como configuro todo

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;

En mi sistema, esto me da 12,872,738 filas en la tabla. Si intento cada una de las consultas anteriores (modificada para SELECT INTO así que no necesito esperar a que termine de imprimir los resultados en SSMS), obtengo los siguientes resultados:

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%

Si observa los planes de consulta, se vuelve bastante obvio por qué: al agregar cualquier tipo de elemento no dinámico o agregado (o el cielo no permita STRING_SPLIT ), terminará con todo tipo de operadores adicionales que no necesita (y obliga al plan ir en paralelo, quitando recursos que otras consultas podrían desear). Por contrato, la solución basada en CASE no es paralela, se ejecuta muy rápidamente y es increíblemente simple.

En este caso, a menos que tenga recursos ilimitados (no los tiene), debe elegir el enfoque más simple y rápido.

Hubo una pregunta sobre qué hacer si necesita seguir agregando nuevas columnas y expandir la declaración del caso. Sí, esto se vuelve difícil de manejar, pero también lo hace cualquier otra solución. Si este es realmente un flujo de trabajo plausible, entonces debe rediseñar su tabla. Lo que quieres probablemente se parece a esto:

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;

Ciertamente, esto no está exento de posibles problemas de rendimiento y requerirá un ajuste cuidadoso del índice, pero es la mejor manera de manejar un número arbitrario de marcas de tiempo potenciales

En caso de que se eliminen las respuestas, aquí están las versiones que estaba comparando (en orden)

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


Prueba esto:

SELECT call_case, (SELECT MAX(call_case) FROM ( VALUES (MAX(date1)), (MAX(date2)) ,(max(date3)) ) MyAlias(call_case) ) FROM #indebtedness group by call_case


Use una expresión CASE :

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;

Manifestación

Tenga en cuenta que algunas bases de datos, como MySQL, SQL Server y SQLite, admiten una función escalar. SQL Server no lo hace, por lo que podemos usar una expresión CASE como solución alternativa.

Editar:

Parece que en su tabla real, una o más de las tres columnas de fecha podrían tener valores NULL . Podemos adaptar la consulta anterior de la siguiente manera:

SELECT call_case, CASE WHEN (date1 > date2 OR date2 IS NULL) AND (date1 > date3 OR date3 IS NULL) THEN date1 WHEN date2 > date3 OR date3 IS NULL THEN date2 ELSE date3 END AS [Latest Date] FROM #indebtedness;

Manifestación


SQL FIDDLE

Use MAX()

SELECT call_case, (SELECT Max(v) FROM (VALUES (date1), (date2), (date3),...) AS value(v)) as [MostRecentDate] FROM #indebtedness

CASE uso

SELECT CASE WHEN Date1 >= Date2 AND Date1 >= Date3 THEN Date1 WHEN Date2 >= Date1 AND Date2 >= Date3 THEN Date2 WHEN Date3 >= Date1 AND Date3 >= Date2 THEN Date3 ELSE Date1 END AS MostRecentDate FROM #indebtedness