如何在几列的最大值中每行返回1个值:

的表

[Number, Date1, Date2, Date3, Cost]

我需要返回这样的东西:

[Number, Most_Recent_Date, Cost]

查询?


当前回答

使用CROSS APPLY (2005+) ....

SELECT MostRecentDate 
FROM SourceTable
    CROSS APPLY (SELECT MAX(d) MostRecentDate FROM (VALUES (Date1), (Date2), (Date3)) AS a(d)) md

其他回答

这是一个古老的答案,在很多方面都有问题。

请参阅https://stackoverflow.com/a/6871572/194653,它有更多的赞,与sql server 2008+一起工作,并处理空值等。

原创但有问题的答案:

你可以使用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

问题:选择给定实体的最小速率值 要求:代理费率可以为空

[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回答的启发

如果您正在使用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

不幸的是,拉斯的答案虽然看似显而易见,但却有一个关键的缺陷。它不能处理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

以下两个示例中的任何一个都可以工作:

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

第二个是对拉塞夫克的答案的补充。

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