Antworten:
Nun, Sie können die CASE-Anweisung verwenden:
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
[Für Microsoft SQL Server 2008 und höher können Sie die einfachere Antwort von Sven unten in Betracht ziehen.]
Hier ist eine weitere schöne Lösung für die Max
Funktionalität mit T-SQL und SQL Server
SELECT [Other Fields],
(SELECT Max(v)
FROM (VALUES (date1), (date2), (date3),...) AS value(v)) as [MaxDate]
FROM [YourTableName]
Wenn Sie MySQL verwenden, können Sie verwenden
SELECT GREATEST(col1, col2 ...) FROM table
Es gibt 3 weitere Methoden, bei denen UNPIVOT
(1) bei weitem die schnellste ist, gefolgt von Simulated Unpivot (3), das viel langsamer als (1), aber immer noch schneller als (2) ist.
CREATE TABLE dates
(
number INT PRIMARY KEY ,
date1 DATETIME ,
date2 DATETIME ,
date3 DATETIME ,
cost INT
)
INSERT INTO dates
VALUES ( 1, '1/1/2008', '2/4/2008', '3/1/2008', 10 )
INSERT INTO dates
VALUES ( 2, '1/2/2008', '2/3/2008', '3/3/2008', 20 )
INSERT INTO dates
VALUES ( 3, '1/3/2008', '2/2/2008', '3/2/2008', 30 )
INSERT INTO dates
VALUES ( 4, '1/4/2008', '2/1/2008', '3/4/2008', 40 )
GO
UNPIVOT
)SELECT number ,
MAX(dDate) maxDate ,
cost
FROM dates UNPIVOT ( dDate FOR nDate IN ( Date1, Date2,
Date3 ) ) as u
GROUP BY number ,
cost
GO
SELECT number ,
( SELECT MAX(dDate) maxDate
FROM ( SELECT d.date1 AS dDate
UNION
SELECT d.date2
UNION
SELECT d.date3
) a
) MaxDate ,
Cost
FROM dates d
GO
UNPIVOT
);WITH maxD
AS ( SELECT number ,
MAX(CASE rn
WHEN 1 THEN Date1
WHEN 2 THEN date2
ELSE date3
END) AS maxDate
FROM dates a
CROSS JOIN ( SELECT 1 AS rn
UNION
SELECT 2
UNION
SELECT 3
) b
GROUP BY Number
)
SELECT dates.number ,
maxD.maxDate ,
dates.cost
FROM dates
INNER JOIN MaxD ON dates.number = maxD.number
GO
DROP TABLE dates
GO
Eines der beiden folgenden Beispiele funktioniert:
SELECT MAX(date_columns) AS max_date
FROM ( (SELECT date1 AS date_columns
FROM data_table )
UNION
( SELECT date2 AS date_columns
FROM data_table
)
UNION
( SELECT date3 AS date_columns
FROM data_table
)
) AS date_query
Die zweite ist eine Ergänzung zu Lassevks Antwort.
SELECT MAX(MostRecentDate)
FROM ( 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 data_table
) AS date_query
DECLARE @TableName TABLE (Number INT, Date1 DATETIME, Date2 DATETIME, Date3 DATETIME, Cost MONEY)
INSERT INTO @TableName
SELECT 1, '20000101', '20010101','20020101',100 UNION ALL
SELECT 2, '20000101', '19900101','19980101',99
SELECT Number,
Cost ,
(SELECT MAX([Date])
FROM (SELECT Date1 AS [Date]
UNION ALL
SELECT Date2
UNION ALL
SELECT Date3
)
D
)
[Most Recent Date]
FROM @TableName
Skalarfunktionen verursachen alle Arten von Leistungsproblemen. Daher ist es besser, die Logik nach Möglichkeit in eine Inline-Tabellenwertfunktion zu packen. Dies ist die Funktion, mit der ich einige benutzerdefinierte Funktionen ersetzt habe, bei denen die Min / Max-Daten aus einer Liste von bis zu zehn Daten ausgewählt wurden. Beim Testen meines Datensatzes mit 1 Million Zeilen dauerte die Skalarfunktion mehr als 15 Minuten, bevor ich die Abfrage abbrach. Die Inline-TVF dauerte 1 Minute. Dies entspricht der Zeit, die für die Auswahl der Ergebnismenge in einer temporären Tabelle erforderlich ist. Um dies zu verwenden, rufen Sie die Funktion entweder über eine Unterabfrage in SELECT oder über eine CROSS APPLY auf.
CREATE FUNCTION dbo.Get_Min_Max_Date
(
@Date1 datetime,
@Date2 datetime,
@Date3 datetime,
@Date4 datetime,
@Date5 datetime,
@Date6 datetime,
@Date7 datetime,
@Date8 datetime,
@Date9 datetime,
@Date10 datetime
)
RETURNS TABLE
AS
RETURN
(
SELECT Max(DateValue) Max_Date,
Min(DateValue) Min_Date
FROM (
VALUES (@Date1),
(@Date2),
(@Date3),
(@Date4),
(@Date5),
(@Date6),
(@Date7),
(@Date8),
(@Date9),
(@Date10)
) AS Dates(DateValue)
)
SELECT
CASE
WHEN Date1 >= Date2 AND Date1 >= Date3 THEN Date1
WHEN Date2 >= Date3 THEN Date2
ELSE Date3
END AS MostRecentDate
Dies ist etwas einfacher zu schreiben und überspringt Bewertungsschritte, da die case-Anweisung der Reihe nach ausgewertet wird.
Leider hat Massees Antwort , obwohl sie offensichtlich erscheint, einen entscheidenden Fehler. Es kann keine NULL-Werte verarbeiten. Jeder einzelne NULL-Wert führt dazu, dass Date1 zurückgegeben wird. Leider wird jeder Versuch, dieses Problem zu beheben, extrem chaotisch und lässt sich nicht sehr gut auf 4 oder mehr Werte skalieren.
Die erste Antwort von databyss sah (und ist) gut aus. Es war jedoch nicht klar, ob die Antwort leicht auf 3 Werte aus einem Join mit mehreren Tabellen anstatt auf die einfacheren 3 Werte aus einer einzelnen Tabelle extrapoliert werden kann. Ich wollte vermeiden, eine solche Abfrage in eine Unterabfrage umzuwandeln, um maximal 3 Spalten zu erhalten. Außerdem war ich mir ziemlich sicher, dass die hervorragende Idee von databyss ein wenig aufgeräumt werden kann.
Also ohne weiteres, hier ist meine Lösung (abgeleitet von der Idee von databyss).
Es verwendet Cross-Joins, bei denen Konstanten ausgewählt werden, um den Effekt eines Multi-Table-Joins zu simulieren. Es ist wichtig zu beachten, dass alle erforderlichen Aliase korrekt ausgeführt werden (was nicht immer der Fall ist), wodurch das Muster durch zusätzliche Spalten recht einfach und ziemlich skalierbar bleibt.
DECLARE @v1 INT ,
@v2 INT ,
@v3 INT
--SET @v1 = 1 --Comment out SET statements to experiment with
--various combinations of NULL values
SET @v2 = 2
SET @v3 = 3
SELECT ( SELECT MAX(Vals)
FROM ( SELECT v1 AS Vals
UNION
SELECT v2
UNION
SELECT v3
) tmp
WHERE Vals IS NOT NULL -- This eliminates NULL warning
) AS MaxVal
FROM ( SELECT @v1 AS v1
) t1
CROSS JOIN ( SELECT @v2 AS v2
) t2
CROSS JOIN ( SELECT @v3 AS v3
) t3
Problem: Wählen Sie den Mindestpreis, der einem Unternehmen zugewiesen wird. Anforderungen: Die Agentursätze können null sein
[MinRateValue] =
CASE
WHEN ISNULL(FitchRating.RatingValue, 100) < = ISNULL(MoodyRating.RatingValue, 99)
AND ISNULL(FitchRating.RatingValue, 100) < = ISNULL(StandardPoorsRating.RatingValue, 99)
THEN FitchgAgency.RatingAgencyName
WHEN ISNULL(MoodyRating.RatingValue, 100) < = ISNULL(StandardPoorsRating.RatingValue , 99)
THEN MoodyAgency.RatingAgencyName
ELSE ISNULL(StandardPoorsRating.RatingValue, 'N/A')
END
Inspiriert von dieser Antwort von Nat
Wenn Sie SQL Server 2005 verwenden, können Sie die UNPIVOT-Funktion verwenden. Hier ist ein vollständiges Beispiel:
create table dates
(
number int,
date1 datetime,
date2 datetime,
date3 datetime
)
insert into dates values (1, '1/1/2008', '2/4/2008', '3/1/2008')
insert into dates values (1, '1/2/2008', '2/3/2008', '3/3/2008')
insert into dates values (1, '1/3/2008', '2/2/2008', '3/2/2008')
insert into dates values (1, '1/4/2008', '2/1/2008', '3/4/2008')
select max(dateMaxes)
from (
select
(select max(date1) from dates) date1max,
(select max(date2) from dates) date2max,
(select max(date3) from dates) date3max
) myTable
unpivot (dateMaxes For fieldName In (date1max, date2max, date3max)) as tblPivot
drop table dates
CROSS APPLY verwenden (für 2005+) ....
SELECT MostRecentDate
FROM SourceTable
CROSS APPLY (SELECT MAX(d) MostRecentDate FROM (VALUES (Date1), (Date2), (Date3)) AS a(d)) md
Ab SQL Server 2012 können wir IIF verwenden .
DECLARE @Date1 DATE='2014-07-03';
DECLARE @Date2 DATE='2014-07-04';
DECLARE @Date3 DATE='2014-07-05';
SELECT IIF(@Date1>@Date2,
IIF(@Date1>@Date3,@Date1,@Date3),
IIF(@Date2>@Date3,@Date2,@Date3)) AS MostRecentDate
DECLARE @Date1 DATE='2014-08-01'; DECLARE @Date2 DATE=null; DECLARE @Date3 DATE='2014-07-05'; /*this gets returned*/
select IIF(@Date1 > @Date2 or @Date2 is null, IIF(@Date1 > @Date3 or @Date3 is null, @Date1, @Date3), IIF(@Date2 > @Date3 or @Date3 is null, @Date2, @Date3)) as MostRecentDate
Ich bevorzuge Lösungen, die auf dem Fall basieren, in dem ich davon ausgehe, dass sie den geringsten Einfluss auf den möglichen Leistungsabfall haben sollten, verglichen mit anderen möglichen Lösungen wie Cross-Apply, values (), benutzerdefinierten Funktionen usw.
Hier ist die Case-When-Version, die mit den meisten möglichen Testfällen Nullwerte verarbeitet:
SELECT
CASE
WHEN Date1 > coalesce(Date2,'0001-01-01') AND Date1 > coalesce(Date3,'0001-01-01') THEN Date1
WHEN Date2 > coalesce(Date3,'0001-01-01') THEN Date2
ELSE Date3
END AS MostRecentDate
, *
from
(values
( 1, cast('2001-01-01' as Date), cast('2002-01-01' as Date), cast('2003-01-01' as Date))
,( 2, cast('2001-01-01' as Date), cast('2003-01-01' as Date), cast('2002-01-01' as Date))
,( 3, cast('2002-01-01' as Date), cast('2001-01-01' as Date), cast('2003-01-01' as Date))
,( 4, cast('2002-01-01' as Date), cast('2003-01-01' as Date), cast('2001-01-01' as Date))
,( 5, cast('2003-01-01' as Date), cast('2001-01-01' as Date), cast('2002-01-01' as Date))
,( 6, cast('2003-01-01' as Date), cast('2002-01-01' as Date), cast('2001-01-01' as Date))
,( 11, cast(NULL as Date), cast('2002-01-01' as Date), cast('2003-01-01' as Date))
,( 12, cast(NULL as Date), cast('2003-01-01' as Date), cast('2002-01-01' as Date))
,( 13, cast('2003-01-01' as Date), cast(NULL as Date), cast('2002-01-01' as Date))
,( 14, cast('2002-01-01' as Date), cast(NULL as Date), cast('2003-01-01' as Date))
,( 15, cast('2003-01-01' as Date), cast('2002-01-01' as Date), cast(NULL as Date))
,( 16, cast('2002-01-01' as Date), cast('2003-01-01' as Date), cast(NULL as Date))
,( 21, cast('2003-01-01' as Date), cast(NULL as Date), cast(NULL as Date))
,( 22, cast(NULL as Date), cast('2003-01-01' as Date), cast(NULL as Date))
,( 23, cast(NULL as Date), cast(NULL as Date), cast('2003-01-01' as Date))
,( 31, cast(NULL as Date), cast(NULL as Date), cast(NULL as Date))
) as demoValues(id, Date1,Date2,Date3)
order by id
;
und das Ergebnis ist:
MostRecent id Date1 Date2 Date3
2003-01-01 1 2001-01-01 2002-01-01 2003-01-01
2003-01-01 2 2001-01-01 2003-01-01 2002-01-01
2003-01-01 3 2002-01-01 2001-01-01 2002-01-01
2003-01-01 4 2002-01-01 2003-01-01 2001-01-01
2003-01-01 5 2003-01-01 2001-01-01 2002-01-01
2003-01-01 6 2003-01-01 2002-01-01 2001-01-01
2003-01-01 11 NULL 2002-01-01 2003-01-01
2003-01-01 12 NULL 2003-01-01 2002-01-01
2003-01-01 13 2003-01-01 NULL 2002-01-01
2003-01-01 14 2002-01-01 NULL 2003-01-01
2003-01-01 15 2003-01-01 2002-01-01 NULL
2003-01-01 16 2002-01-01 2003-01-01 NULL
2003-01-01 21 2003-01-01 NULL NULL
2003-01-01 22 NULL 2003-01-01 NULL
2003-01-01 23 NULL NULL 2003-01-01
NULL 31 NULL NULL NULL
Sie können eine Funktion erstellen, in der Sie die Daten übergeben und die Funktion dann wie unten beschrieben zur select-Anweisung hinzufügen. Wählen Sie Nummer, dbo.fxMost_Recent_Date (Datum1, Datum2, Datum3), Kosten
create FUNCTION fxMost_Recent_Date
(@ Date1 smalldatetime, @ Date2 smalldatetime, @ Date3 smalldatetime) RETURNS smalldatetime AS BEGIN DECLARE @Result smalldatetime
declare @MostRecent smalldatetime
set @MostRecent='1/1/1900'
if @Date1>@MostRecent begin set @MostRecent=@Date1 end
if @Date2>@MostRecent begin set @MostRecent=@Date2 end
if @Date3>@MostRecent begin set @MostRecent=@Date3 end
RETURN @MostRecent
ENDE
Basierend auf der ScottPletcher -Lösung von http://www.experts-exchange.com/Microsoft/Development/MS-SQL-Server/Q_24204894.html habe ich eine Reihe von Funktionen (z. B. GetMaxOfDates3, GetMaxOfDates13) erstellt, um max von bis zu 13 Datumswerten mit UNION ALL. Siehe T-SQL-Funktion, um das Maximum an Werten aus derselben Zeile abzurufen. Zum Zeitpunkt des Schreibens dieser Funktionen habe ich jedoch noch keine UNPIVOT-Lösung in Betracht gezogen
Die obige Tabelle enthält eine Gehaltsliste für Mitarbeiter mit Gehalt1, Gehalt2, Gehalt3, Gehalt4 als Spalten. Die folgende Abfrage gibt den Maximalwert aus vier Spalten zurück
select
(select Max(salval) from( values (max(salary1)),(max(salary2)),(max(salary3)),(max(Salary4)))alias(salval)) as largest_val
from EmployeeSalary
Wenn Sie die obige Abfrage ausführen, wird die Ausgabe als größter Wert (10001) ausgegeben.
Die Logik der obigen Abfrage ist wie folgt:
select Max(salvalue) from(values (10001),(5098),(6070),(7500))alias(salvalue)
Ausgabe wird 10001 sein
Hier ist eine gute Lösung:
CREATE function [dbo].[inLineMax] (@v1 float,@v2 float,@v3 float,@v4 float)
returns float
as
begin
declare @val float
set @val = 0
declare @TableVal table
(value float )
insert into @TableVal select @v1
insert into @TableVal select @v2
insert into @TableVal select @v3
insert into @TableVal select @v4
select @val= max(value) from @TableVal
return @val
end
Ich weiß nicht, ob es sich um SQL usw. handelt. In der M $ ACCESS-Hilfe gibt es eine Funktion namens MAXA(Value1;Value2;...)
, die dies tun soll.
Hoffnung kann jemandem helfen.
PD: Werte können Spalten oder berechnete Werte usw. sein.
MAXA
ist eine Excel-Funktion , kein Zugriff.
WHEN Date1 > Date2 AND Date1 > Date3 THEN Date1; WHEN Date2 > Date3 THEN Date3; ELSE Date3
?