获取列和关联列名称之间的最大值

时间:2015-02-27 22:41:31

标签: sql sql-server

我希望获得一组列中的最大值以及列名。例如,给定:

| Id | A | B | C |
------------------
| 1  | 1 | 2 | 3 |

我希望:

| Id | Column | Value |
------------------------
| 1  |    C   |   3   |

我已经获得了查询的一部分来确定最大的值,但我也在努力展示它来自哪个列。

SELECT Id,
(SELECT Max(v) 
FROM (VALUES (A), (B), (C)) AS value(v)) as MaxValue
FROM [dbo].[MyTable]

我觉得我很亲近,但我不知道如何完成这个。谢谢!

2 个答案:

答案 0 :(得分:3)

试试这个:

SELECT  Id, mx.*
FROM    [dbo].[MyTable]
OUTER APPLY (
    SELECT  TOP(1) value.* 
    FROM    (VALUES ('A', A), ('B', B), ('C', C)) AS value(col, v) 
    WHERE   value.v IS NOT NULL 
    ORDER BY value.v DESC
) mx

警告:在这种情况下(MAX(col)),条件

WHERE   value.v IS NOT NULL 

不是强制性的,但是如果某人想要获得MIN值并且在没有WHERE Col IS NOT NULL的情况下使用相同的技术,它可以防止错误的结果:

OUTER APPLY (
    SELECT  TOP(1) value.* 
    FROM    (VALUES ('A', A), ('B', B), ('C', C)) AS value(col, v) 
    ORDER BY value.v ASC -- ASC for minimum
) mn

如果其中一列包含NULL,则上述解决方案(OUTER APPLY () mn)将返回NULL而不是MIN(聚合函数忽略NULL):

SELECT  MIN(ColA) --> 11 / correct result
FROM    (VALUES (NULL), (11), (22)) x(ColA)
-- vs.
SELECT  TOP(1) ColA --> NULL / wrong result
FROM    (VALUES (NULL), (11), (22)) x(ColA)
ORDER BY x.ColA -- ASC for minimum

答案 1 :(得分:2)

攻击问题的一种方法(不是声称它是最好的方法)是对列值进行排名,然后从该数据集中选择我们想要的内容。

首先取消您的记录:

select id
       , columnName
       , columnValue
from mytable
     unpivot
     (
        columnValue for columnName in(a,b,c)
     ) as unpvt

接下来,我们可以根据我们想要看到的输出为这些值分配排名。要对ID 1st的最大列值进行排名,我们添加:

select id
       , columnName
       , columnValue
       , rank() over (partition by id order by columnValue DESC, columnName DESC) as rankVal
    from mytable
    unpivot
    (
        columnValue for columnName in(a,b,c)
    ) as unpvt

请注意,在我们的rank()上方,如果我们只按columnValue订购,如果两列的最大值相同,您最终会得到两个等级1。然后,下一步将返回ID的两个记录。如果这是您希望看到的输出,请从, columnName DESC订单中移除rank()

现在我们已经对我们的值进行了排名,我们可以从该结果集中选择我们想要的值:

with cteUnpivot(id, columnName, columnValue, rankVal)
AS
(
    select id
           , columnName
           , columnValue
           , rank() over (partition by id order by columnValue DESC, columnName DESC) as rankVal
    from mytable
    unpivot
    (
        columnValue for columnName in(a,b,c)
    ) as unpvt
)

select id
       , columnName as [Column]
       , columnValue as [Value]
from cteUnpivot
where rankVal = 1