20 ответов:
Ну, вы можете использовать оператор CASE:
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[для Microsoft SQL Server 2008 и выше, вы можете рассмотреть более простой ответ Свена ниже.]
вот еще одно хорошее решение для
Maxфункциональность с использованием T-SQL и SQL ServerSELECT [Other Fields], (SELECT Max(v) FROM (VALUES (date1), (date2), (date3),...) AS value(v)) as [MaxDate] FROM [YourTableName]
есть еще 3 метода, где
UNPIVOT(1) является самым быстрым на сегодняшний день, а затем моделируется Unpivot (3), который намного медленнее, чем (1), но все же быстрее, чем (2)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Решение 1 (
UNPIVOT)SELECT number , MAX(dDate) maxDate , cost FROM dates UNPIVOT ( dDate FOR nDate IN ( Date1, Date2, Date3 ) ) as u GROUP BY number , cost GOрешение 2 (Sub query per row)
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Решение 3 (Имитация
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
любой из двух примеров ниже будет работать:
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второй является дополнением к lassevk это ответ.
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
скалярная функция вызывает всевозможные проблемы с производительностью, поэтому лучше обернуть логику во встроенную табличную функцию, если это возможно. Это функция, которую я использовал для замены некоторых пользовательских функций, которые выбрали минимальные/максимальные даты из списка до десяти дат. При тестировании на моем наборе данных из 1 миллиона строк скалярная функция заняла более 15 минут, прежде чем я убил запрос встроенный TVF занял 1 минуту, что является тем же количеством времени, что и выбор результирующего набора во временный стол. Чтобы использовать этот вызов функции из подзапроса в SELECT или CROSS APPLY.
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) )
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
для T-SQL (MSSQL 2008+)
SELECT (SELECT MAX(MyMaxName) FROM ( VALUES (MAX(iSortCode)), (MAX(Field2)) ) MyAlias(MyMaxName) ) FROM MyTable1
SELECT CASE WHEN Date1 >= Date2 AND Date1 >= Date3 THEN Date1 WHEN Date2 >= Date3 THEN Date2 ELSE Date3 END AS MostRecentDateэто немного легче записать и пропускает шаги оценки, поскольку оператор case оценивается по порядку.
к сожалению ответ Лассе, хотя, казалось бы, очевидно, имеет изъян. Он не может обрабатывать нулевые значения. Ни одного нулевого значения Дата1 возвращается. К сожалению, любая попытка исправить эту проблему, как правило, становится чрезвычайно грязной и не масштабируется до 4 или более значений очень красиво.
первый ответ databyss выглядел (и есть) хорошо. Однако было неясно, будет ли ответ легко экстраполироваться на 3 значения из объединения нескольких таблиц вместо более простых 3 значений из одной таблицы. Я хотел избежать превращения такого запроса в подзапрос, чтобы получить максимум 3 столбца, также я был уверен, что отличная идея databyss может быть немного очищена.
итак, без дальнейших церемоний, вот мое решение (полученное из идеи databyss).
Он использует перекрестные соединения, выбирая константы, чтобы имитировать эффект объединения нескольких таблиц. Важно отметить, что все необходимые псевдонимы проходят правильно (что это не всегда так), и это сохраняет шаблон довольно простым и довольно масштабируемым с помощью дополнительных столбцов.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
проблема: выберите минимальное значение скорости, заданное для объекта Требования: агентские ставки могут быть нулевыми
[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
Если вы используете SQL Server 2005, вы можете использовать функцию UNPIVOT. Вот полный пример:
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 (для 2005+) ....
SELECT MostRecentDate FROM SourceTable CROSS APPLY (SELECT MAX(d) MostRecentDate FROM (VALUES (Date1), (Date2), (Date3)) AS a(d)) md
из SQL Server 2012 мы можем использовать IIF.
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
пожалуйста, попробуйте использовать
UNPIVOT:SELECT MAX(MaxDt) MaxDt FROM tbl UNPIVOT (MaxDt FOR E IN (Date1, Date2, Date3) )AS unpvt;
вы можете создать функцию, где вы передаете даты, а затем добавить функцию в инструкцию select, как показано ниже. выберите номер, dbo.fxMost_Recent_Date (Date1,Date2,Date3), стоимость
create FUNCTION fxMost_Recent_Date( @Date1 smalldatetime, @Date2 smalldatetime, @Date3 smalldatetime ) Возвращает тип данных smalldatetime КАК НАЧИНАТЬ Объявить @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конец
на основе ScottPletcher ' S решение от http://www.experts-exchange.com/Microsoft/Development/MS-SQL-Server/Q_24204894.html Я создал набор функций (например , GetMaxOfDates3, GetMaxOfDates13), чтобы найти максимум до 13 значений даты с помощью UNION ALL. Смотрите функция T-SQL, чтобы получить максимум значений из той же строки Однако я не рассматривал решение UNPIVOT на момент написания этих функций
другой способ использовать СЛУЧАЙ, КОГДА
SELECT CASE true WHEN max(row1) >= max(row2) THEN CASE true WHEN max(row1) >= max(row3) THEN max(row1) ELSE max(row3) end ELSE CASE true WHEN max(row2) >= max(row3) THEN max(row2) ELSE max(row3) END END FROM yourTable
Я не знаю, если это на SQL, и т. д... на M$ACCESS help есть функция с именем
MAXA(Value1;Value2;...)вот и предполагается сделать такое.Надежда может помочь кому-то.
P. D.: значения могут быть столбцами или вычисленными и т. д.
вот хорошее решение:
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
Comments