SQL - 获取具有最大值的列的索引

Yuk*_*ura 5 sql-server

我有一个包含样本数据的表格如下.

col1    col2    col3
4       6       9
7       1       5
Run Code Online (Sandbox Code Playgroud)

我想得到列的索引,其值与该行的最大值匹配,如果它们相等,则忽略后者.

例如,结果应该是return

3 (because col3 has maximum value 9)
1 (because col1 has maximum value 7)
Run Code Online (Sandbox Code Playgroud)

请注意,列数未定义,因此我需要一般解决方案.

谢谢

Stu*_*tLC 3

对此的更通用的解决方案(即 N 列)是将列逆透视为行,然后可以应用窗口函数来获得每组列“行”的分组最大值。然而,每行都需要某种类型的键,以便可以以行方式应用最大值(以允许重新组装原始行)。Guid我通过添加代理来完成此操作newId()。请注意,这将返回每行中具有最高值的列 NAME:

WITH MyTableWithRowId AS
(
    SELECT newId() AS Id, *
    FROM MyTable
),
Unpivoted AS
(
    SELECT Ndx, Id, col, ROW_NUMBER() OVER (PARTITION BY Id ORDER BY col DESC) AS Rnk
    FROM 
    MyTableWithRowId tbl
    UNPIVOT
    (
      col for Ndx in(col1, col2, col3)
    ) p
)
SELECT Ndx
FROM Unpivoted
WHERE Rnk = 1
Run Code Online (Sandbox Code Playgroud)

SqlFiddle在这里

编辑,只是“1,2,3”而不是列的名称(col1,col2,col3)

根据 @Giorgi 的评论,如果您确实想要每行中列的(基于一个的)序号位置,您可以重新连接到 DMV,例如INFORMATION_SCHEMA.COLUMNS查找序号,尽管在我看来,这将是非常脆弱的策略。

WITH MyTableWithRowId AS
(
    SELECT newId() AS Id, col1, col2, col3
    FROM MyTable
),
TheOrdinalPositionOfColumns AS
(
    SELECT COLUMN_NAME, ORDINAL_POSITION
    FROM INFORMATION_SCHEMA.COLUMNS
    WHERE TABLE_NAME = 'MyTable'
),
Unpivoted AS
(
    SELECT Ndx, Id, col, ROW_NUMBER() OVER (PARTITION BY Id ORDER BY col DESC) AS Rnk
    FROM 
    MyTableWithRowId tbl
    UNPIVOT
    (
      col for Ndx in(col1, col2, col3)
    ) p
)
SELECT topoc.ORDINAL_POSITION AS ColumnOrdinalPosition
FROM Unpivoted
JOIN TheOrdinalPositionOfColumns topoc ON Unpivoted.Ndx = topoc.COLUMN_NAME
WHERE Rnk = 1;
Run Code Online (Sandbox Code Playgroud)

使用 Giorgi 的列命名更新了 Fiddle