In T-SQL di SQL Server non esiste una funzione che, passate 3 date presenti sulla stessa riga, restituisca la massima tra le 3.

Si può comunque raggiungere lo scopo con l'uso dell'istruzione CASE.

Dati di esempio

Per l'esempio uso questa tabella con 3 righe, ogni riga ha la data più alta in un campo differente

T-SQL: Tabella di esempio

CREATE TABLE [dbo].[TableDates](
	[ID] [int] NOT NULL,
	[DateA] [datetime2](7) NULL,
	[DateB] [datetime2](7) NULL,
	[DateC] [datetime2](7) NULL,
 CONSTRAINT [PK_TableDates] PRIMARY KEY CLUSTERED ([ID] ASC)
);

INSERT INTO [dbo].[TableDates] VALUES(1, '2022-01-10', '2022-06-10', '2022-11-10');
INSERT INTO [dbo].[TableDates] VALUES(2, '2022-05-16', '2022-05-21', '2022-05-02');
INSERT INTO [dbo].[TableDates] VALUES(3, '2022-08-30', '2022-08-29', '2022-08-12');

MaxDate

Si può costruire una SELECT che tramite l'istruzione CASE ritorni la data massima

T-SQL: Max date

SELECT
 
  CASE 
    WHEN [DateA] > [DateB] AND [DateA] > [DateC] THEN [DateA] 
    WHEN [DateB] > [DateA] AND [DateB] > [DateC] THEN [DateB]
    ELSE [DateC]
  END AS [MaxDate],

FROM [dbo].[TableDates]
in questo modo abbiamo ottenuto la funzione MaxDate presente in altri linguaggi.

Si può ulteriormente affinare aggiungendo, nei risultati, anche la colonna scelta come massima data

T-SQL: MaxDate con Choice

SELECT [ID], [DateA], [DateB], [DateC],
 
  CASE 
    WHEN [DateA] > [DateB] AND [DateA] > [DateC] THEN [DateA] 
    WHEN [DateB] > [DateA] AND [DateB] > [DateC] THEN [DateB]
    ELSE [DateC]
  END AS [MaxDate],

  CASE 
    WHEN [DateA] > [DateB] AND [DateA] > [DateC] THEN 'A' 
    WHEN [DateB] > [DateA] AND [DateB] > [DateC] THEN 'B'
    ELSE 'C'
  END AS [Choice]
FROM [dbo].[TableDates]
da come risultato
#class=table-striped 
ID;DateA;DateB;DateC;MaxDate;Choice
1;2022-01-10;2022-06-10;2022-11-10;2022-11-10;C
2;2022-05-16;2022-05-21;2022-05-02;2022-05-21;B
3;2022-08-30;2022-08-29;2022-08-12;2022-08-30;A

MaxDate con null

In molte situazioni può capitare di avere alcune date nulle

T-SQL: Dati di esempio aggiuntivi

INSERT INTO [dbo].[TableDates] VALUES(10, '2022-01-10', '2022-06-10', null);
INSERT INTO [dbo].[TableDates] VALUES(20, '2022-05-16', null, '2022-05-02');
INSERT INTO [dbo].[TableDates] VALUES(30, null, '2022-08-29', '2022-08-12');
con questi nuovi dati, se eseguiamo la query di prima otteniamo
#class=table-striped 
ID;DateA;DateB;DateC;MaxDate;Choice
1;2022-01-10;2022-06-10;2022-11-10;2022-11-10;C
2;2022-05-16;2022-05-21;2022-05-02;2022-05-21;B
3;2022-08-30;2022-08-29;2022-08-12;2022-08-30;A
10;2022-01-10;2022-06-10;NULL;NULL;C
20;2022-05-16;NULL;2022-05-02;2022-05-02;C
30;NULL;2022-08-29;2022-08-12;2022-08-12;C
in pratica si finisce sempre nell'ELSE della CASE in quanto il confronto di maggioranza (>) con valori null fallisce.

Soluzione

Per far funzionare il confronto dobbiamo usare l'istruzione COALESCE(valore, dataMin) passando, come secondo parametro, una data che sarà sicuramente inferiore a quelle presenti nel dataset.

T-SQL: MaxDate with null

DECLARE @minDate datetime2 = '1/1/1'  -- considero che una delle date possa essere nulla

SELECT [ID], [DateA], [DateB], [DateC],
 
  CASE 
    WHEN COALESCE([DateA], @minDate) > COALESCE([DateB], @minDate) AND COALESCE([DateA], @minDate) > COALESCE([DateC], @minDate) THEN [DateA] 
    WHEN COALESCE([DateB], @minDate) > COALESCE([DateA], @minDate) AND COALESCE([DateB], @minDate) > COALESCE([DateC], @minDate) THEN [DateB]
    ELSE [DateC]
  END AS [MaxDate],

  CASE 
    WHEN COALESCE([DateA], @minDate) > COALESCE([DateB], @minDate) AND COALESCE([DateA], @minDate) > COALESCE([DateC], @minDate) THEN 'A' 
    WHEN COALESCE([DateB], @minDate) > COALESCE([DateA], @minDate) AND COALESCE([DateB], @minDate) > COALESCE([DateC], @minDate) THEN 'B'
    ELSE 'C'
  END AS [Choice]
FROM [dbo].[TableDates]
a questo punto il risultato è corretto
ID;DateA;DateB;DateC;MaxDate;Choice
1;2022-01-10;2022-06-10;2022-11-10;2022-11-10;C
2;2022-05-16;2022-05-21;2022-05-02;2022-05-21;B
3;2022-08-30;2022-08-29;2022-08-12;2022-08-30;A
10;2022-01-10;2022-06-10;NULL;2022-06-10;B
20;2022-05-16;NULL;2022-05-02;2022-05-16;A
30;NULL;2022-08-29;2022-08-12;2022-08-29;B
Tags:
T-SQL66 SQL Server100 SQL90
Potrebbe interessarti anche: