Sql 如何获得一行中所有列的最高值';相等值的名称

Sql 如何获得一行中所有列的最高值';相等值的名称,sql,sql-server,tsql,Sql,Sql Server,Tsql,我需要获得行中的最高值以及列的名称。问题是在一个分区中可能有几个相等的值。因此,我期望的结果是在一列中获得最高值,在这种情况下,所有列的名称都用逗号分隔 这个问题与我的前一个问题密切相关: 让我们使用上一个问题中Shnugo的例子 DECLARE @tbl TABLE(ID INT IDENTITY,d1 DATE, d2 DATE, d3 DATE); INSERT INTO @tbl VALUES ('20180101','20180102','20180103') --one max

我需要获得行中的最高值以及列的名称。问题是在一个分区中可能有几个相等的值。因此,我期望的结果是在一列中获得最高值,在这种情况下,所有列的名称都用逗号分隔

这个问题与我的前一个问题密切相关:

让我们使用上一个问题中Shnugo的例子

DECLARE @tbl TABLE(ID INT IDENTITY,d1 DATE, d2 DATE, d3 DATE);
INSERT INTO @tbl VALUES
('20180101','20180102','20180103')  --one max value
,('20170101','20190102','20190102'); --two max values

对于ID=2,有两个max值,因此我要完成的是一个具有ID列、max_date列和第三列名称的表。因此,对于ID=2,我希望得到两列的名称(d2,d3)。

您可以尝试使用类似的代码来获取信息并插入到表中。您必须根据需要更新下面的
案例逻辑以添加附加条件

DECLARE @tbl TABLE(ID INT IDENTITY,d1 DATE, d2 DATE, d3 DATE);
INSERT INTO @tbl VALUES
('20180301','20180102','20180103')  --one max value
,('20170101','20190102','20190102'); --two max values

SELECT ID, LEFT(MAXDateInfo,10) AS maxdate, RIGHT(maxdateInfo,2) as ColumnName
FROM
(SELECT ID,CASE WHEN d1 > d2 AND d1 > d3 THEN CONCAT(d1,'-','d1')
               WHEN d2 > d1 AND d2 > d3 THEN CONCAT(d2,'-','d2')
               WHEN d3 > d1 AND d3 > d3 THEN CONCAT(d3,'-','d3')
           END AS MAXDateInfo
FROM @tbl) as t

您可以尝试使用类似的代码获取信息并插入到表中。您必须根据需要更新下面的
案例
逻辑以添加其他条件

DECLARE @tbl TABLE(ID INT IDENTITY,d1 DATE, d2 DATE, d3 DATE);
INSERT INTO @tbl VALUES
('20180301','20180102','20180103')  --one max value
,('20170101','20190102','20190102'); --two max values

SELECT ID, LEFT(MAXDateInfo,10) AS maxdate, RIGHT(maxdateInfo,2) as ColumnName
FROM
(SELECT ID,CASE WHEN d1 > d2 AND d1 > d3 THEN CONCAT(d1,'-','d1')
               WHEN d2 > d1 AND d2 > d3 THEN CONCAT(d2,'-','d2')
               WHEN d3 > d1 AND d3 > d3 THEN CONCAT(d3,'-','d3')
           END AS MAXDateInfo
FROM @tbl) as t
试着这样做:

DECLARE @tbl TABLE(ID INT IDENTITY,d1 DATE, d2 DATE, d3 DATE);
INSERT INTO @tbl VALUES
 ('20180101','20180102','20180103')  --one max value
,('20170101','20190102','20190102'); --two max values

WITH cte AS
(
    SELECT TOP 1 WITH TIES
           t.ID 
          ,y.value('text()[1]','date') d
          ,y.value('local-name(.)','varchar(100)') c
    FROM @tbl t
    CROSS APPLY(SELECT d1,d2,d3 FOR XML PATH('d'),TYPE) A(x)
    CROSS APPLY x.nodes('/d/*') B(y) 
    ORDER BY DENSE_RANK() OVER(PARTITION BY ID ORDER BY y.value('text()[1]','date') DESC)
)
SELECT cte1.ID
      ,cte1.d 
      ,STUFF((SELECT ',' + cte2.c 
        FROM cte cte2 
        WHERE cte1.ID=cte2.ID
        FOR XML PATH('')),1,1,'') cs
FROM cte cte1
GROUP BY ID,d;
使用SQL Server 2017+时,您应该更好地使用

我添加了一些解释

试着这样做:

DECLARE @tbl TABLE(ID INT IDENTITY,d1 DATE, d2 DATE, d3 DATE);
INSERT INTO @tbl VALUES
 ('20180101','20180102','20180103')  --one max value
,('20170101','20190102','20190102'); --two max values

WITH cte AS
(
    SELECT TOP 1 WITH TIES
           t.ID 
          ,y.value('text()[1]','date') d
          ,y.value('local-name(.)','varchar(100)') c
    FROM @tbl t
    CROSS APPLY(SELECT d1,d2,d3 FOR XML PATH('d'),TYPE) A(x)
    CROSS APPLY x.nodes('/d/*') B(y) 
    ORDER BY DENSE_RANK() OVER(PARTITION BY ID ORDER BY y.value('text()[1]','date') DESC)
)
SELECT cte1.ID
      ,cte1.d 
      ,STUFF((SELECT ',' + cte2.c 
        FROM cte cte2 
        WHERE cte1.ID=cte2.ID
        FOR XML PATH('')),1,1,'') cs
FROM cte cte1
GROUP BY ID,d;
使用SQL Server 2017+时,您应该更好地使用


我已经添加了一些解释

编辑问题添加一些示例数据&期望的结果会有帮助。您是否尝试了MAX(列名称)?结果与您想要的结果有何不同?编辑问题添加一些示例数据&想要的结果会有帮助。您是否尝试了MAX(列名称)?结果与您想要的结果有何不同?谢谢,它可以工作,但问题是执行时间超过20分钟(仍在运行),尽管我在所有临时表上创建了聚集索引。理想情况下,如果一个ID有多个最大日期,我希望所有列都有名称,但在我看来,这可能太耗时了。@Arkadiusz如果有这么多行,这似乎是错误的设计。。。您的日期列应该位于相关的“状态”表中。。。另一个选项是insert和update上的触发器,或者是将附加列设置为所需值的perstant计算列。您可以维护一个侧表,每当其中一个日期发生更改时,您可以在其中添加一行。您不应该计算数百万行的动态信息。顺便说一句:DBA讨厌在db服务器上使用CPU消耗的方法…谢谢,它可以工作,但问题是执行时间超过20分钟(仍在运行),尽管我在所有临时表上创建了聚集索引。理想情况下,如果一个ID有多个最大日期,我希望所有列都有名称,但在我看来,这可能太耗时了。@Arkadiusz如果有这么多行,这似乎是错误的设计。。。您的日期列应该位于相关的“状态”表中。。。另一个选项是insert和update上的触发器,或者是将附加列设置为所需值的perstant计算列。您可以维护一个侧表,每当其中一个日期发生更改时,您可以在其中添加一行。您不应该计算数百万行的动态信息。顺便说一句:DBA讨厌db服务器上的CPU消耗方法。。。