TableName
[Number, Date1, Date2, Date3, Cost]
我需要返回如下内容:
[Number, Most_Recent_Date, Cost]
查询?
#1 楼
好吧,您可以使用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及更高版本,您可以在下面考虑Sven的简单答案。]
#2 楼
这是使用T-SQL和SQL Server的Max
功能的另一个不错的解决方案。SELECT [Other Fields],
(SELECT Max(v)
FROM (VALUES (date1), (date2), (date3),...) AS value(v)) as [MaxDate]
FROM [YourTableName]
评论
SQL版本必须为> = 2008。
–丹尼尔(Daniel)
2011-09-14 15:23
这在2008年确实可以很好地工作,并且可以处理NULL。非常好的解决方案。
– nycdan
2012年2月13日14:40在
@Cheburek:从value(v)开始,“ value”是虚拟表的别名,“ v”是日期值的虚拟列的名称。
–乔纳斯·林肯(Jonas Lincoln)
2012年8月13日在14:03
太好了在哪里可以找到此Value()虚拟表的文档?
–我的另一个我
13年2月7日在14:18
我最初也不理解VALUE(v)。如果您想了解VALUE,请尝试以下查询,该查询创建一个虚拟1列表:SELECT * FROM(VALUES(1),(5),(1))as listOfValues(columnName)并且此查询创建一个虚拟2列表: SELECT * FROM(VALUES(1,2),(5,3),(1,4))作为tableOfValues(columnName1,ColumnName2)现在您可以理解为什么该示例查询中包含AS值(v)。我的最终查询如下所示:SELECT Max(currentValues)as Max FROM(VALUES(12),(25),(35))AS allCurrents(currentValues)在这种情况下,它将选择最大值为35。
–杰克逊
2013年3月7日在16:14
#3 楼
如果您使用的是MySQL,则可以使用SELECT GREATEST(col1, col2 ...) FROM table
评论
标签是sqlserver
– Codewerks
08年12月1日在19:34
是的,但仍然是一个非常有用的答案,因为人们在参考MySQL时发现了这个问题。
– philfreo
2010年8月30日23:20
从8.1开始在PostgreSQL中也可用。
–冷冻火焰
2015年11月10日,9:51
不能很好地处理NULL,但是如果您在列值周围合并(col1,0),则将使用气体烹饪,请参见以下答案stackoverflow.com/questions/9831851/…
–斯坦·奎因(Stan Quinn)
18-2-9在4:51
那么这个解决方案呢:stackoverflow.com/a/2166693/4824854
–桑德堡
19年7月11日在7:50
#4 楼
还有3种方法,其中UNPIVOT
(1)是迄今为止最快的,其次是Simulated 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(每行子查询)
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
评论
真好我没有意识到PIVOT和UNPIVOT操作员。
– Sako73
2011年9月7日19:30在
知道哪个版本的SQL Server支持透视/取消透视吗?
–幻灭
2012年1月23日12:52
@CraigYoung SQL Server 2005(COMPATIBILITY_LEVEL设置为90)。
– Paul Syfrett
2012年10月5日17:53
#5 楼
以下两个示例中的任何一个都可以使用: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
评论
第一个答案是好的,但可以大大简化。第二个答案不适用于NULL值。试图解决该问题变得非常混乱。
–幻灭
2012年1月23日12:47
您应该使用UNION ALL而不是UNION,以避免不必要的隐式DISTINCT操作。
–JamieSee
16-10-25在15:36
#6 楼
对于T-SQL(MSSQL 2008+)SELECT
(SELECT
MAX(MyMaxName)
FROM ( VALUES
(MAX(Field1)),
(MAX(Field2))
) MyAlias(MyMaxName)
)
FROM MyTable1
评论
早在2011年就提出了这种确切的解决方案
– Andriy M
6月18日8:42
#7 楼
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
评论
对我来说,可以在任何SQL版本中工作,很好的解决方案
– klapshin
4月16日21:25
#8 楼
标量函数会导致各种性能问题,因此最好将逻辑包装到内联表值函数中。这是我用来替换一些用户定义函数的函数,这些函数从最多十个日期的列表中选择了最小/最大日期。在我的100万行数据集上进行测试时,标量函数花费了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)
)
#9 楼
SELECT
CASE
WHEN Date1 >= Date2 AND Date1 >= Date3 THEN Date1
WHEN Date2 >= Date3 THEN Date2
ELSE Date3
END AS MostRecentDate
由于按顺序评估case语句,因此写起来稍微容易些,并且跳过评估步骤。
评论
小心。如果Date2为NULL,则答案为Date3;否则,答案为Date3。即使Date1较大。
–幻灭
2012年1月24日上午8:36
#10 楼
不幸的是,拉瑟的答案虽然看似显而易见,但却有一个严重的缺陷。它不能处理NULL值。任何单个NULL值都会导致返回Date1。不幸的是,任何解决该问题的尝试都将变得非常混乱,并且无法很好地扩展到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
#11 楼
问题:选择提供给实体的最低费率值要求:代理费率可以为空
[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
受Nat的回答
启发
#12 楼
如果使用的是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
评论
我认为我更喜欢UNION示例。
–兰斯·费舍尔
08年12月1日在19:38
“如何返回每列最多几列的一个值”
– Niikola
09年9月9日在6:59
#13 楼
使用CROSS APPLY(适用于2005 +)....SELECT MostRecentDate
FROM SourceTable
CROSS APPLY (SELECT MAX(d) MostRecentDate FROM (VALUES (Date1), (Date2), (Date3)) AS a(d)) md
评论
使用VALUES使其无法在2005年使用。您必须用等效的SELECT值UNION ALL SELECT值系列替换VALUES。
– Andriy M
6月18日8:40
#14 楼
在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
评论
很好,但是不处理空值。例如:DECLARE @ Date1 DATE ='2014-08-01'; DECLARE @ Date2 DATE =空; DECLARE @ Date3 DATE ='2014-07-05'; / *这将返回* /
– jumxozizi
18年1月25日在11:43
我们可以这样处理空值:选择IIF(@ Date1> @ Date2或@ Date2为空,IIF(@ Date1> @ Date3或@ Date3为空,@ Date1,@ Date3),IIF(@ Date2> @ Date3或@ Date3为null,@ Date2,@ Date3))作为MostRecentDate
– jumxozizi
18年1月25日在11:55
#15 楼
请尝试使用UNPIVOT
:SELECT MAX(MaxDt) MaxDt
FROM tbl
UNPIVOT
(MaxDt FOR E IN
(Date1, Date2, Date3)
)AS unpvt;
#16 楼
我更喜欢基于大小写的解决方案,当时我的假设是,与其他可能的解决方案(例如具有交叉应用,values(),自定义函数等的解决方案)相比,它对可能的性能下降的影响最小。这里是案例,当版本使用大多数可能的测试案例处理空值时:
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
;
,结果是:
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
评论
哦,上帝,谢谢你,先生!我花了很多时间来做这种怪异的公式,仍然给了我零陷的感觉,现在我看到了隧道尽头的光芒。
– Max S.
19年3月15日在18:16
#17 楼
您可以在传递日期的地方创建一个函数,然后将其添加到如下所示的select语句中。选择数字,dbo.fxMost_Recent_Date(Date1,Date2,Date3),成本
create FUNCTION fxMost_Recent_Date
(
@ Date1 smalldatetime,
@ Date2 smalldatetime,
@ Date3 smalldatetime
)
返回smalldatetime
AS
BEGIN
声明@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
END
#18 楼
基于http://www.experts-exchange.com/Microsoft/Development/MS-SQL-Server/Q_24204894.html中ScottPletcher的解决方案,我创建了一组函数(例如GetMaxOfDates3,GetMaxOfDates13)用于使用UNION ALL最多可以找到13个日期值。请参见T-SQL函数从同一行中获取最大值。
但是在编写这些函数时我还没有考虑UNPIVOT解决方案
#19 楼
使用CASE的另一种方式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
#20 楼
这是一个很好的解决方案: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
#21 楼
我不知道它是否在SQL上,等等。在M $ ACCESS帮助上,有一个名为MAXA(Value1;Value2;...)
的函数应该可以这样做。希望可以帮助某人。
PD:值可以是列或计算得出的值,等等。
评论
Microsoft Access是一个完全不同的产品。此外,您是否可以提出对此类功能的主张?我从未在Access中看到或听说过此消息。
–deutschZuid
16年7月14日在23:44
MAXA是Excel函数,而不是Access。
–费利克斯·夏娃(Felix Eve)
18/09/14在8:47
#22 楼
上面的表是一个以薪金1,工资2,工资3,工资4为列的员工薪水表。下面的查询将返回四列中的最大值。select
(select Max(salval) from( values (max(salary1)),(max(salary2)),(max(salary3)),(max(Salary4)))alias(salval)) as largest_val
from EmployeeSalary
在上面的查询中运行将给出输出结果为largest_val(10001)
上述查询的逻辑如下:
select Max(salvalue) from(values (10001),(5098),(6070),(7500))alias(salvalue)
输出将为10001
评论
这几乎是@sven在11月29日发布的解决方案的副本
–卢克
3月14日17:09
评论
当Date1> Date2 AND Date1> Date3 THEN Date1时使用是否足够?当Date2> Date3 THEN Date3时; ELSE Date3?
–特雷布
2011年6月30日15:15
答案很明显,但是它不适用于NULL值,并且试图解决这个问题变得非常混乱。
–幻灭
2012年1月23日12:49
死了这个较早的帖子,但是您可以将每个日期包装到一个COALESCE中以处理NULL。然后,这些WHEN语句之一如下:当Date1> = COALESCE(Date2,'')AND Date1> = COALESCE(Date3,'')THEN Date3时(对其他when相同)
– Bill Sambrone
2014年2月20日在17:50
对于那些来这里寻找MySQL方式的人,请查看@ bajafresh4life回复:stackoverflow.com/a/331873/1412157
– LucaM
15年5月22日在13:23
顺便说一句,即使Date3> Date1,当Date2为null时,它也会返回Date1。
– jumxozizi
17年9月20日在12:55