使用左连接选择特定日期的行

时间:2014-02-17 12:45:51

标签: php mysql sql

我目前正在开发一个简单的员工安排工具,并且遇到SQL查询问题。为了解释我的问题,让我们使用这两个非常抽象的表。

第一个表只包含员工

employees
======================
empId | name    | ...
----------------------
10    | Scott   |
11    | Schrute |
12    | Halpert |
13    | Howard  |

在第二个表格中,您可以按天找到每位员工的分配任务。

tasks
==============================================
tasId | name    | task     | date       | ...
----------------------------------------------
10    | Scott   | Support  | 2014-02-17 |
11    | Scott   | Bugfix   | 2014-02-18 |
12    | Halpert | Bugfix   | 2014-02-17 |
13    | Halpert | Develop  | 2014-02-18 |
14    | Howard  | Support  | 2014-02-17 |

现在我想知道2月17日员工在做什么,或者他们当天没有计划任务。我使用以下SQL查询来执行此操作。

SELECT e.name, t.task
FROM employees e LEFT JOIN tasks t ON e.name = t.name
WHERE date IS NULL OR date = DATE('2014-02-17')

结果完全符合我的需要:

name    | task
--------------------
Scott   | Support
Schrute | NULL
Halpert | Bugfix
Howard  | Support

现在我的问题。如果我想看到2月18日的任务,我得到这个结果集:

name    | task
--------------------
Scott   | Bugfix
Schrute | NULL
Halpert | Develop

原因很明显,霍华德任务的日期既不是NULL,也不等于2014-02-18 ..什么是获得理想结果的最佳方法?

我使用MySQL和PHP。

(抱歉这个愚蠢的标题,我想不出更好的事情......)

2 个答案:

答案 0 :(得分:1)

将过滤器移动到连接谓词:

SELECT e.name, t.task
FROM employees e 
LEFT JOIN tasks t ON e.name = t.name AND t.date = DATE('2014-02-18');

您的查询将仅返回完全没有任务的人员,或者在指定日期执行任务。它将省略具有任务但未在指定日期的人员。考虑加入样本数据的结果,没有where子句:

empId | name    | task     | date       | ...
----------------------------------------|
10    | Scott   | Support  | 2014-02-17 |
10    | Scott   | Bugfix   | 2014-02-18 |
11    | Schrute | NULL     |   NULL     |
12    | Halpert | Bugfix   | 2014-02-17 |
12    | Halpert | Develop  | 2014-02-18 |
13    | Howard  | Support  | 2014-02-17 |

正如您所看到的,霍华德没有Date = 2014-02-18,或者Date为空的记录,这就是霍华德没有记录的原因。将过滤器添加到连接谓词时,结果将变为:

empId | name    | task     | date       | ...
----------------------------------------|
10    | Scott   | Bugfix   | 2014-02-18 |
11    | Schrute | NULL     |   NULL     |
12    | Halpert | Develop  | 2014-02-18 |
13    | Howard  | NULL     |   NULL     |

我认为这是理想的结果。

答案 1 :(得分:0)

您可以使用

UNIX_TIMESTAMP(`date`) = 0

看起来你有一些数据存储为'0000-00-00'并且它不是空的,所以如上所述添加额外的OR条件也会返回这些数据。