SQL 将 MAX 应用于具有非空行的左连接表

Posted

技术标签:

【中文标题】SQL 将 MAX 应用于具有非空行的左连接表【英文标题】:SQL apply MAX to left join table having non null rows 【发布时间】:2020-07-23 12:42:33 【问题描述】:

表名:国家

id country_name
1  USA
2  GERMANY
3  RUSSIA

表名:用户


id user_name  points country_id
1  user1      20     1
2  user2      10     2
3  user3      11     2

结果应该是最高分的国家用户,如果没有用户可用,则只有国家(第三条记录),如下所示

country_name user_name points
USA          user1     20
GERMANY      user3     11
RUSSIA       (null)    (null)

目前我正在使用以下查询,但有时会花费太多时间,例如当我有 100000 条记录时。

SELECT c.country_name,u.user_name,u.points FROM country c
LEFT JOIN user u on u.country_id = c.id 
WHERE (u.points = (SELECT MAX(points) AS points FROM user WHERE user.id = u.id) OR u.points IS NULL)

那么,有没有其他方法可以在时间上更有效地做到这一点。

已经谢谢了!

【问题讨论】:

Oracle 标签更具体,所以我猜您使用的是 Oracle。请标记您真正使用的数据库。 抱歉,由于堆栈溢出的声誉,无法添加新标签,我使用的是 Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 【参考方案1】:

你可以使用ROW_NUMBER():

SELECT c.country_name, u.user_name, u.points
FROM country c LEFT JOIN
     (SELECT u.*,
             ROW_NUMBER() OVER (PARTITION BY u.country_id ORDER BY u.points DESC) as seqnum
      FROM user u
      WHERE u.points IS NOT NULL
     ) u
     ON u.country_id = c.id AND u.seqnum = 1;

注意:这会为每个国家/地区返回一个用户,即使前一个用户存在平局。如果您想要所有这些,请使用RANK() 而不是ROW_NUMBER()

【讨论】:

谢谢,这个解决方案在我的情况下效果更好,查询性能提高了 234 秒到 2 秒,再次感谢。

以上是关于SQL 将 MAX 应用于具有非空行的左连接表的主要内容,如果未能解决你的问题,请参考以下文章

SQL中有几种连接?有啥区别?(左连右连内连和外连?)

mysql连接查询

mysql4.0中一表关联多表左连接sql写法:

Spark数据框左连接应在右侧添加默认行而不是null的连接

使用 And 条件将 Linq 左连接到 SQL [重复]

带条件sql的左外连接