【问题标题】:Convert subquery to join转换子查询以加入
【发布时间】:2012-02-07 09:52:21
【问题描述】:

是否可以将以下子查询转换为 JOIN,最好不使用派生表?

SELECT * FROM users u
LEFT JOIN user_groups ug ON u.usergroupid=ug.groupid
WHERE
u.userstatus=1 AND
ug.groupstatus=1 AND
ug.grouprank>=(SELECT grouprank FROM user_groups WHERE groupkey='users')

user_groups 表如下所示:

+-------------+---------------------+------+-----+---------+----------------+
| Field       | Type                | Null | Key | Default | Extra          |
+-------------+---------------------+------+-----+---------+----------------+
| groupid     | tinyint(3) unsigned | NO   | PRI | NULL    | auto_increment |
| groupkey    | varchar(8)          | NO   |     | NULL    |                |
| grouprank   | smallint(6)         | NO   |     | NULL    |                |
| groupstatus | tinyint(1) unsigned | NO   |     | NULL    |                |
+-------------+---------------------+------+-----+---------+----------------+

用户表如下所示:

+--------------+---------------------+------+-----+---------+----------------+
| Field        | Type                | Null | Key | Default | Extra          |
+--------------+---------------------+------+-----+---------+----------------+
| userid       | int(10) unsigned    | NO   | PRI | NULL    | auto_increment |
| username     | varchar(32)         | NO   |     | NULL    |                |
| userpassword | varchar(32)         | NO   |     | NULL    |                |
| usergroupid  | tinyint(3) unsigned | NO   |     | NULL    |                |
| userstatus   | tinyint(1) unsigned | NO   |     | NULL    |                |
+--------------+---------------------+------+-----+---------+----------------+

【问题讨论】:

  • 请编辑您的问题以描述相关表格的方案,或者至少是user_groups 表格。
  • 我已将这两个表格添加到说明中。
  • 为什么要LEFT JOIN user_groups 然后在WHERE 子句中检查ug.groupstatus=1
  • 你想用这个查询达到什么目的?
  • LEFT JOIN 是一种习惯。它应该是一个 INNER JOIN。

标签: mysql sql join subquery


【解决方案1】:

假设恰好一条user_groups 记录具有groupkey = 'users'(否则您的查询无效),您的查询等效于:

SELECT u.*,
       ug1.*
  FROM users u
  LEFT
  JOIN user_groups ug1
    ON u.usergroupid = ug1.groupid
  LEFT
  JOIN user_groups ug2
    ON ug2.groupkey = 'users' -- not a real join condition
 WHERE u.userstatus = 1
   AND ug1.groupstatus = 1
   AND ug1.grouprank >= ug2.grouprank
;

但请注意,LEFT JOINs 实际上最终以 INNER JOINs 的形式工作,因为您的 WHERE 子句取决于连接是否成功。所以你可能真的想要这样的东西:

SELECT u.*,
       ug1.*
  FROM users u
  LEFT
  JOIN user_groups ug1
    ON u.usergroupid = ug1.groupid
   AND ug1.groupstatus = 1
  LEFT
  JOIN user_groups ug2
    ON ug2.groupkey = 'users'
   AND ug1.grouprank >= ug2.grouprank
 WHERE u.userstatus = 1
;

【讨论】:

  • 是的,groupkey 检查唯一性,所以总是只有 1 个值。您的查询也有效。谢谢:)
【解决方案2】:

我认为这就是您要寻找的东西——试一试。

SELECT * FROM users u
LEFT JOIN user_groups ug ON u.usergroupid=ug.groupid
JOIN user_groups ug2 ON ug.grouprank >= ug2.grouprank AND ug2.groupkey = 'users'
WHERE
u.userstatus=1 AND
ug.groupstatus=1

【讨论】:

  • 注意:ruakh 的回答还进一步完善了您的查询。值得阅读他的回答,了解如何改进查询,甚至比您要求的更好。
  • 我同意。两者都非常相似并且都可以工作,但是我已经接受了您的回答,因为您首先回答了。
猜你喜欢
  • 1970-01-01
  • 2021-06-20
  • 2014-01-21
  • 2021-04-06
  • 2020-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多