mysql - LEFT JOIN 不返回左侧表中的所有记录

标签 mysql sql join left-join where-clause

SELECT d.mt_code,
       d.dep_name,
       d.service_name,
       COUNT(*)
FROM DepartmentService AS d
LEFT JOIN tbl_outgoing AS t ON d.mt_code = t.depCode
WHERE d.service_type = 'MT'
  AND t.smsc = "mobitelMT"
  AND t.sendDate BETWEEN '2014-07-01' AND '2014-07-02'
GROUP BY d.mt_code

DepartmentService 表包含有关提供服务的部门的详细信息。 tbl_outgoing 表包含由客户完成的特定服务发生的所有交易。在 WHERE 子句中,应满足两个自助餐厅,它们是 service_type = 'MT' 和 smsc = "newMT"。我想要一份报告,其中显示所有部门在给定时间段内的交易情况。我使用了 LEFT JOIN 因为我想获得所有部门。 SQL 工作正常并得到我想要的结果,除了,

当特定时间段内没有针对特定服务的交易时,部门也将被忽略。我想要做的是将结果集中的部门和 COUNT(*) 列显示为 0。

我该怎么做?

最佳答案

问题可能是您正在使用 where 条件对连接表进行过滤,该条件也会过滤连接中没有匹配项的部门服务,移动连接中的过滤并仅保留 d 上的过滤器在 where 子句中:

SELECT d.mt_code,
   d.dep_name,
   d.service_name,
   COUNT(t.id)
FROM DepartmentService AS d
LEFT JOIN tbl_outgoing AS t 
  ON d.mt_code = t.depCode 
    AND t.smsc = "mobitelMT"
    AND t.sendDate BETWEEN '2014-07-01' AND '2014-07-02'
WHERE d.service_type = 'MT'
GROUP BY d.mt_code

为了解释为什么会发生这种情况,我将向您介绍您的查询和我的查询所发生的情况,作为数据集,我将使用它:

states
 ____ _________ 
| id | state   |
|  1 | Germany |
|  2 | Italy   |
|  3 | Sweden  |
|____|_________|

cities

 ____ ________ ___________ ____________
| id | city   | state_fk  | population |
|  1 | Berlin |        1  |         10 |
|  2 | Milan  |        2  |          5 |
|____|________|___________|____________|

首先,我将完成您的查询。

SELECT s.id, s.state, c.population, c.city
FROM states s
LEFT JOIN cities c
ON c.state_fk = s.id
WHERE c.population < 10

所以让我们一步一步来,您选择三个州,左加入以以下城市结尾的城市:

 ____ _________ ____________ ________
| id | state   | population | city   |
|  1 | Germany |         10 | Berlin |
|  2 | Italy   |          5 | Milan  |
|  3 | Sweden  |       NULL | NULL   |
|____|_________|____________|________|

您使用 WHERE c.population < 10 过滤人口,此时您的左边是:

 ____ _________ ____________ ________
| id | state   | population | city   |
|  2 | Italy   |          5 | Milan  |
|____|_________|____________|________|

你失去了德国,因为柏林人口是 10 但你也失去了瑞典,它有 NULL,如果你想保留空值,你应该在查询中指定它:

WHERE (c.population < 10 OR IS NULL c.population)

哪个返回:

 ____ _________ ____________ ________
| id | state   | population | city   |
|  2 | Italy   |          5 | Milan  |
|  3 | Sweden  |       NULL | NULL   |
|____|_________|____________|________|

现在我的查询:

SELECT s.id, s.state, c.population, c.city
FROM states s
LEFT JOIN cities c
ON c.state_fk = s.id
  AND c.population < 10

在加入两者之前,我们过滤表城市(使用 AND c.population < 10 之后的 ON 条件),剩下的是:

 ____ ________ ___________ ____________
| id | city   | state_fk  | population |
|  2 | Milan  |        2  |          5 |
|____|________|___________|____________|

因为米兰是唯一一个人口少于 10 人的城市,现在我们可以连接两个表:

 ____ _________ ____________ ________
| id | state   | population | city   |
|  1 | Germany |       NULL | NULL   |
|  2 | Italy   |          5 | Milan  |
|  3 | Sweden  |       NULL | NULL   |
|____|_________|____________|________|

如您所见,左侧表中的数据得以保留,因为过滤条件应用于城市表。


结果集会根据您想要实现的目标而变化,例如,如果您想过滤德国,因为柏林的人口少于 10 人,并保留瑞典,您应该使用第一种方法添加 IS NULL 条件,如果您想保留相反,您应该使用第二种方法并在左连接的右侧预过滤表。

关于mysql - LEFT JOIN 不返回左侧表中的所有记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25544986/

相关文章:

mysql - 如何连接两个都有 COUNT 和分组的查询而不令人头疼?

mysql - 如何恢复MySQL root用户的权限?

php - 将用户信息存储在 wp 数据库中并在注册时使用单独的数据库

mysql - 获取Mysql中 super 父级的所有子级id

mysql - JPA @NamedQuery 以按位 AND (&) 作为条件

sql - 我需要在 AdventureWorks (SQL 2005) 上进行慢速查询

mysql - 左外连接到生成的表?

mysql - 为日期范围内的每一天创建一行?

sql - 传递给 SQL 的数组可以有多大,其中 column_value IN (Array) 是多少?

mysql - 将 MySQL 子查询重写为 join