Sql 如何获得一行中所有列的最高值';相等值的名称
我需要获得行中的最高值以及列的名称。问题是在一个分区中可能有几个相等的值。因此,我期望的结果是在一列中获得最高值,在这种情况下,所有列的名称都用逗号分隔 这个问题与我的前一个问题密切相关: 让我们使用上一个问题中Shnugo的例子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
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消耗方法。。。