[英]SQL filter rows without join
我总是被不必要的加入“惹恼”。 但是在这种情况下,我想知道是否可以不使用join。
这是我的表的一个示例:
id | team | score
1 | 1 | 300
2 | 1 | 257
3 | 2 | 127
4 | 2 | 533
5 | 3 | 459
这就是我要的:
team | score | id
1 | 300 | 1
2 | 533 | 4
3 | 459 | 5
进行如下查询:(基本上:谁是每个团队中最好的球员)
SELECT team, MAX(score) AS score, id
FROM my_table
GROUP BY team
但是我得到这样的东西:
team | score | id
1 | 300 | 1
2 | 533 | 3
3 | 459 | 5
但这并不是第三位获得533分的球员,因此结果并不一致。
是否可以在不加入表格的情况下获得真实的结果? 如何实现呢?
您可以使用变量:
SELECT id, team, score
FROM (
SELECT id, team, score,
@seq := IF(@t = team, @seq,
IF(@t := team, @seq + 1, @seq + 1)) AS seq,
@grp := IF(@t2 = team, @grp + 1,
IF(@t2 := team, 1, 1)) AS grp
FROM mytable
CROSS JOIN (SELECT @seq := 0, @t := 0, @grp := 0, @t2 := 0) AS vars
ORDER BY score DESC) AS t
WHERE seq <= 3 AND grp = 1
可变@seq
每个作为记录按降序正在处理一个新的团队成立时递增score
顺序。 变量@grp
用于枚举每个team
分区内的记录。 @grp = 1
记录是team
score
最高的记录。
您可以通过使用子查询来执行以下操作而无需联接:
SELECT id, team, score
FROM table1 a
WHERE score = (SELECT MAX(score) FROM table1 b WHERE a.team = b.team);
但是,在大表中,这可能会非常慢,因为您必须为表中的每一行运行整个子查询。
但是,使用join过滤结果是没有错的:
SELECT id, team, score FROM table1 a
INNER JOIN (
SELECT MAX(score) score, team
FROM table1
GROUP BY team
) b ON a.score = b.score AND a.team = b.team
尽管联接本身非常昂贵,但是无论表中有多少行,这种方式都只需要运行两个实际查询。 因此,在大表中,此方法仍可以比第一种带有子查询的方法快数百倍(甚至数千倍)。
不幸的是,MySQL不支持像ROW_NUMBER()
这样的窗口函数,该函数可以轻松解决此问题。
有几种方法可以做到这一点:
NOT EXISTS()
:
SELECT * FROM YourTable t
WHERE NOT EXISTS(SELECT 1 FROM YourTable s
WHERE t.team = s.team AND s.score > t.score)
NOT IN()
:
SELECT * FROM YourTable t
WHERE (t.team,t.score) IN(SELECT s.team,MAX(s.score)
FROM YourTable s
GROUP BY s.team)
相关查询:
SELECT distinct t.id,t.team,
(SELECT s.score FROM YourTable s
WHERE s.team = t.team
ORDER BY s.score DESC
LIMIT 1)
FROM YourTable t
或我了解您已经拥有的加入。
编辑 :我的话语还可以,您可以使用@GiorgosBetsos解决方案之类的变量来完成。
您可以执行以下操作:
SELECT team, score, id
FROM (SELECT *
,RANK() OVER
(PARTITION BY team ORDER BY score DESC) AS Rank
FROM my_table) ranked_result
WHERE Rank = 1;
有关排名功能的一些信息: Clicketyclickclick
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.