假设有一个表名" 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...
有人可以帮忙解释一下它是如何运作的吗?
答案 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。
如果你真的想要一个TOP 1
加入,那么这样就可以了。只有当您拥有非唯一的值时,才需要SELECT
:
INNER
但是这个与你在解决方案2中所做的非常相似。这里有fiddle。