T-SQL:基于 MAX 选择列(其他列)
Posted
技术标签:
【中文标题】T-SQL:基于 MAX 选择列(其他列)【英文标题】:T-SQL: Selecting Column Based on MAX(Other Column) 【发布时间】:2011-04-10 11:08:23 【问题描述】:我希望有一种不使用子查询的简单方法:
场景:您有“TableA”,其中包含“Key”、“SubKey”和“Value”列。我需要获取给定“键”的 MAX(“子键”) 的“值”。
所以如果表格包含行:
KEY SUBKEY VALUE
1 1 100
1 2 200
1 3 300
对于 Key = 1,我需要值 300。我希望这样做:
SELECT
VALUE
FROM
TableA
WHERE
Key = 1
HAVING
SubKey = MAX(SubKey)
但这是不行的。有没有办法在不执行“WHERE SubKey = (subselect for max subkey)”的情况下做到这一点?
【问题讨论】:
【参考方案1】:很简单,不用join,不用子查询:
SELECT FIRST_VALUE(Value) OVER (ORDER BY SubKey DESC)
FROM TableA
WHERE Key = 1
如果您需要每个键的最大值:
SELECT DISTINCT Key,
FIRST_VALUE(Value) OVER (PARTITION BY Key ORDER BY SubKey DESC)
FROM TableA
【讨论】:
【参考方案2】:OMG Ponie 的 ROW_NUMBER
方法是在所有情况下都最有效的方法,因为如果有两个相同数量的 MAX
值返回比预期更多的记录并破坏可能的记录,它不会失败插入你可能已经被那个recordset
喂饱了。
缺少的一件事是如何在必须返回与每个最大值关联的子键的情况下执行此操作,同时也有多个键。只需将summary
与MIN
和GROUP
“本身”一起加入您的表即可。
WITH summary AS (
SELECT t.*,
ROW_NUMBER() OVER(ORDER BY t.subkey DESC) AS rank
FROM TABLE t
WHERE t.key = 1)
SELECT s.*
FROM summary s
join (select key, min(rank) as rank
from summary
group by key) sMAX
on s.key = sMAX.key and r.rank = sMAX.rank
【讨论】:
【参考方案3】:如果有多个键使用 CTE:
WITH CTE AS
(
SELECT key1, key2, MAX(subkey) AS MaxSubkey
FROM TableA
GROUP BY key1, key2
)
SELECT a.Key1, a.Key2, a.Value
FROM TableA a
INNER JOIN CTE ON a.key1 = CTE.key1 AND a.key2 = CTE.key2 AND
a.subkey = CTE.MaxSubkey
【讨论】:
【参考方案4】:如果您总是只希望一个键值的一行而不是多个键的答案,那么所有连接的东西都是无用的过度构建。只需使用 OMG Ponies 已经为您提供的 TOP 1 查询。
【讨论】:
【参考方案5】:使用自联接:
这将返回所有子键值匹配的值,以防有多个。
SELECT a.value
FROM TABLE a
JOIN (SELECT MAX(t.subkey) AS max_subkey
FROM TABLE t
WHERE t.key = 1) b ON b.max_subkey = a.subkey
WHERE a.key = 1
使用 RANK 和 CTE (SQL Server 2005+):
这将返回所有子键值匹配的值,以防有多个。
WITH summary AS (
SELECT t.*,
RANK() OVER(ORDER BY t.subkey DESC) AS rank
FROM TABLE t
WHERE t.key = 1)
SELECT s.value
FROM summary s
WHERE s.rank = 1
使用 ROW_NUMBER 和 CTE (SQL Server 2005+):
这将返回一行,即使有多个具有相同的子键值...
WITH summary AS (
SELECT t.*,
ROW_NUMBER() OVER(ORDER BY t.subkey DESC) AS rank
FROM TABLE t
WHERE t.key = 1)
SELECT s.value
FROM summary s
WHERE s.rank = 1
使用 TOP:
这将返回一行,即使有多个具有相同的子键值...
SELECT TOP 1
t.value
FROM TABLE t
WHERE t.key = 1
ORDER BY t.subkey DESC
【讨论】:
由于实际查询是几个表链接在一起,我最终选择了“选择前 1 个,有序 desc”方法,因为这似乎是最容易阅读的 @John:这很好,但是如果您需要处理每个键的最高值,那么分析版本(RANK、ROW_NUMBER)更适合。 如果您使用的是 SQL Server 2012 或更高版本,请参阅以下来自 @Nguyen 的答案。 ***.com/a/35477271/269123【参考方案6】:OMG Ponies 采用了大多数方式来做到这一点。还有一个:
SELECT
T1.value
FROM
My_Table T1
LEFT OUTER JOIN My_Table T2 ON
T2.key = T1.key AND
T2.subkey > T1.subkey
WHERE
T2.key IS NULL
T2.key 为 NULL 的唯一时间是 LEFT JOIN 中没有匹配项,这意味着不存在具有更高子键的行。如果多行具有相同(最高)的子键,这将返回多行。
【讨论】:
这非常适合为每个键拉出一行。【参考方案7】:SELECT MAX(Value)
FROM TableA t1
GROUP BY Key, SubKey
HAVING SubKey = (SELECT MAX(SubKey) FROM TableA t2 WHERE t1.Key = t2.Key)
AND Key = 1
【讨论】:
以上是关于T-SQL:基于 MAX 选择列(其他列)的主要内容,如果未能解决你的问题,请参考以下文章
T-SQL基于分隔符拆分列并将拆分后的字符串数组输入到多个表列中
在 LibreOffice 或其他电子表格工具中应用基于行的过滤器而不是基于列的过滤器
SQL 从同一个表(实际上是同一列)中选择两行,基于与其他表的连接