我希望获得一组列中的最大值以及列名。例如,给定:
| 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]
我觉得我很亲近,但我不知道如何完成这个。谢谢!
答案 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