MYSQL LEFT JOIN 和 COUNT 和 GROUP BY
MYSQL LEFT JOIN and COUNT and GROUP BY
我找到了几个与该任务相关的线程,但都没有真正帮助我,或者我没有足够的经验来理解它。
我正在使用 mysql 并且有两个 table user
和 user_rh
。我想要一个用户名列表(按名称排序),其中包含 user_rh
.
中相应的条目数
`user` `user_rh`
------------------ ------------------
| `uid` | `name` | | `uid` | `zaid` |
------------------ ------------------
| 1 | Bob | | 2 | 4 |
| 2 | John | | 2 | 7 |
| 3 | Fred | | 3 | 2 |
| 4 | Peter | ------------------
------------------
所以结果应该是这样的:
--------------------
| `name` | `count` |
--------------------
| Bob | 0 |
| Fred | 1 |
| John | 2 |
| Peter | 0 |
--------------------
我试过这个查询:
SELECT
`user`.`name`,
`user_rh`.`uid`
FROM
`user`
LEFT JOIN
`user_rh`
ON (`user_rh`.`uid`=`user`.`uid`)
ORDER BY
`user`.`name`
方向正确,但这不会 return 计数值:
------------------
| `name` | `uid` |
------------------
| Bob | NULL |
| John | 2 |
| John | 2 |
| Fred | 1 |
| Peter | NULL |
------------------
我以为我只是添加了 COUNT() 和 GROUP BY 命令:
SELECT
`user`.`name`,
COUNT(`user_rh`.`uid`) AS `count`
FROM
`user`
LEFT JOIN
`user_rh`
ON (`user_rh`.`uid`=`user`.`uid`)
GROUP BY
`user_rh`.`uid`
ORDER BY
`user`.`name`
但它向我展示了这样的东西。首先,它提供一个排序的名称列表,其中 count
!=0 列表的最后一个条目是 table user
的第一个条目,其中 count
=0。
------------------
| `name` | `uid` |
------------------
| John | 2 |
| Fred | 1 |
| Bob | 0 |
------------------
我想,我只是以错误的方式组合了命令。
您的第二个查询没问题。只需从第一个 table 开始按用户分组。否则你会把你的 left join
变成 inner join
SELECT
u.name,
COUNT(rh.uid) AS cnt
FROM
`user` u
LEFT JOIN
user_rh rh
ON (rh.uid = u.uid)
GROUP BY
u.uid, u.name
ORDER BY
u.name
它不会将您的 left join 转换为 inner join。当链接到用户时,它只是按 user_rh 中的 uid 分组。您有 3 个不同的 uid(NULL、2 和 1),这就是为什么您的结果中只有 3 行。
当您使用分组子句时,您可以 select 仅具有分组聚合(如 COUNT、SUM、AVG..)的字段或组子句中可用的字段。您可以省略分组,但 Mysql 会自行进行分组,但结果可能不可靠,因为它会选择第一个可用的分组。这就是为什么您的 3 行结果中显示了 Bob。
我找到了几个与该任务相关的线程,但都没有真正帮助我,或者我没有足够的经验来理解它。
我正在使用 mysql 并且有两个 table user
和 user_rh
。我想要一个用户名列表(按名称排序),其中包含 user_rh
.
`user` `user_rh`
------------------ ------------------
| `uid` | `name` | | `uid` | `zaid` |
------------------ ------------------
| 1 | Bob | | 2 | 4 |
| 2 | John | | 2 | 7 |
| 3 | Fred | | 3 | 2 |
| 4 | Peter | ------------------
------------------
所以结果应该是这样的:
--------------------
| `name` | `count` |
--------------------
| Bob | 0 |
| Fred | 1 |
| John | 2 |
| Peter | 0 |
--------------------
我试过这个查询:
SELECT
`user`.`name`,
`user_rh`.`uid`
FROM
`user`
LEFT JOIN
`user_rh`
ON (`user_rh`.`uid`=`user`.`uid`)
ORDER BY
`user`.`name`
方向正确,但这不会 return 计数值:
------------------
| `name` | `uid` |
------------------
| Bob | NULL |
| John | 2 |
| John | 2 |
| Fred | 1 |
| Peter | NULL |
------------------
我以为我只是添加了 COUNT() 和 GROUP BY 命令:
SELECT
`user`.`name`,
COUNT(`user_rh`.`uid`) AS `count`
FROM
`user`
LEFT JOIN
`user_rh`
ON (`user_rh`.`uid`=`user`.`uid`)
GROUP BY
`user_rh`.`uid`
ORDER BY
`user`.`name`
但它向我展示了这样的东西。首先,它提供一个排序的名称列表,其中 count
!=0 列表的最后一个条目是 table user
的第一个条目,其中 count
=0。
------------------
| `name` | `uid` |
------------------
| John | 2 |
| Fred | 1 |
| Bob | 0 |
------------------
我想,我只是以错误的方式组合了命令。
您的第二个查询没问题。只需从第一个 table 开始按用户分组。否则你会把你的 left join
变成 inner join
SELECT
u.name,
COUNT(rh.uid) AS cnt
FROM
`user` u
LEFT JOIN
user_rh rh
ON (rh.uid = u.uid)
GROUP BY
u.uid, u.name
ORDER BY
u.name
它不会将您的 left join 转换为 inner join。当链接到用户时,它只是按 user_rh 中的 uid 分组。您有 3 个不同的 uid(NULL、2 和 1),这就是为什么您的结果中只有 3 行。
当您使用分组子句时,您可以 select 仅具有分组聚合(如 COUNT、SUM、AVG..)的字段或组子句中可用的字段。您可以省略分组,但 Mysql 会自行进行分组,但结果可能不可靠,因为它会选择第一个可用的分组。这就是为什么您的 3 行结果中显示了 Bob。