SQL - 获取最大结果

时间:2015-12-30 06:57:18

标签: sql sql-server database inner-join

假设有一个表名" test"下面:

name    value
n1        1
n2        2
n3        3

现在,我想获得具有最大值的名称,我在下面有一些解决方案:

解决方案1:

SELECT TOP 1 name 
FROM test 
ORDER BY value DESC

解决方案2:

SELECT name 
FROM test 
WHERE value = (SELECT MAX(value) FROM test);

现在,我希望使用join操作来查找结果,比如

SELECT name 
FROM test 
INNER JOIN test ON...

有人可以帮忙解释一下它是如何运作的吗?

2 个答案:

答案 0 :(得分:3)

如果您正在寻找JOIN,那么

SELECT T.name, T.value
    FROM test T
INNER JOIN 
(   SELECT T1.name, T1.value ,
        RANK() OVER (PARTITION BY T1.name ORDER BY T1.value) N
    FROM test T1
    WHERE T1.value IN (SELECT MAX(t2.value) FROM test T2)
)T3 ON T3.N = 1 AND T.name = T3.name

<强> FIDDLE DEMO

select  name, value
from
(
  select  name, value,
    row_number() over(order by value desc) rn
  from test
) src
where rn = 1

<强> FIDDLE DEMO

答案 1 :(得分:0)

首先,请注意,当不唯一时,解决方案1和2可能会给出不同的结果。如果在您的测试数据中会有一个额外的记录('n4',3),那么解决方案1将返回'n3''n4'< / em>,但解决方案2将返回两者。

使用JOIN的解决方案需要表的别名,因为在您开始时,引擎会说不明确的列名'name'。:它不知道是否采取 test 表第一次或第二次出现的 name

以下是完成JOIN版本的方法:

SELECT    t1.name 
FROM      test t1
LEFT JOIN test t2
       ON t2.value > t1.value
WHERE     t2.value IS NULL; 

此查询获取每个记录,并检查是否存在任何具有更高的记录。如果没有,第一条记录将出现在结果中。请注意LEFT的使用:这表示外部联接,因此来自 t1 的记录与 t2 不匹配 - 基于{{1}条件 - 不会立即被拒绝(就像ON的情况一样):事实上,我们想要拒绝所有其他记录,这是用{{1}完成的条款。

理解这种机制的一种方法是查看上面查询的变体,它缺少INNER子句并返回两个表的

WHERE

在您的测试数据上,这将返回:

WHERE

请注意,如果加入SELECT t1.value, t2.value FROM test t1 LEFT JOIN test t2 ON t2.value > t1.value ,则最后一个条目不会出现。但是使用外部联接,现在可以查找t1.value t2.value 1 2 1 3 2 3 3 (null) 值并实际获取将从INNER JOIN中排除的结果中的那些记录。

请注意,当存在重复的时,此查询将提供与解决方案2相同的结果。如果您想只有一个结果,例如解决方案1,那么在NULL之后添加INNER JOIN就足够了。

这是fiddle

替代纯INNER JOIN

如果你真的想要一个TOP 1加入,那么这样就可以了。只有当您拥有非唯一的时,才需要SELECT

INNER

但是这个与你在解决方案2中所做的非常相似。这里有fiddle