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

时间:2014-08-28 09:10:09

标签: mysql sql join left-join where

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' and smsc = "newMT"。我想得到一份报告,显示所有部门在特定时期内的交易。我使用了LEFT JOIN,因为我想要获得所有部门。 SQL工作正常,得到我想要的结果,除了,

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

我该怎么做?

1 个答案:

答案 0 :(得分:4)

问题可能是您使用where条件过滤联接表,该条件还将过滤在联接中不匹配的部门服务,在联接中移动过滤并仅保留过滤器在where子句的d上:

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   |
|____|_________|____________|________|

正如您所看到的,左表中的数据仍然存在,因为过滤条件仅应用 到cities表。


结果集会根据您想要达到的目标而变化,例如,如果您想要过滤德国,因为柏林的人口不足10而且保留瑞典,则应使用第一种方法添加IS NULL条件,如果你想保留它,你应该使用第二种方法并预先过滤左边连接右边的表格。