如何巧妙地使用现有记录表执行日期列表的左连接

Jas*_*bas 2 mysql

我正在使用以下查询来获取两个给定日期之间的日期列表:

SELECT selected_date FROM 
(select adddate('1970-01-01',t4.i*10000 + t3.i*1000 + t2.i*100 + t1.i*10 + t0.i) selected_date from
 (select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t0,
 (select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t1,
 (select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t2,
 (select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t3,
 (select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t4) v
WHERE selected_date BETWEEN '2016-03-08' AND '2016-03-11';
Run Code Online (Sandbox Code Playgroud)

这给了我以下输出:

+---------------+
| selected_date |
+---------------+
| 2016-03-08    |
| 2016-03-09    |
| 2016-03-10    |
| 2016-03-11    |
+---------------+
Run Code Online (Sandbox Code Playgroud)

以下查询为我提供了在特定日期工作所需的所有员工的列表:

SELECT employee.id, employee.firstname
FROM Users employee
LEFT JOIN Table1 table1 ON table1.fId = employee.tId
WHERE table1.day = dayofweek('2016-03-10')
Run Code Online (Sandbox Code Playgroud)

这产生:

+----+-----------+
| id | firstname |
+----+-----------+
|  1 | Mat       |
|  2 | Tom       |
+----+-----------+
Run Code Online (Sandbox Code Playgroud)

如果没有员工需要在给定日期工作,则结果为空。

我有一个第三个表,其中列出了每个员工在某一天的表现:

SELECT * FROM performance;

+----+------------+------------+------+
| id | employeeId |    date    | val  |
+----+------------+------------+------+
|  1 |          1 | 2016-03-08 | 100  |
|  2 |          2 | 2016-03-08 | 90   |
|  3 |          1 | 2016-03-09 | 80   |
|  4 |          2 | 2016-03-09 | 100  |
+----+------------+------------+------+
Run Code Online (Sandbox Code Playgroud)

我想加入以上三个结果以产生:

+----+------------+-----------+------------+------+
| id | employeeId | firstname |    date    | val  |
+----+------------+-----------+------------+------+
|  1 |          1 | Mat       | 2016-03-08 | 100  |
|  2 |          2 | Tom       | 2016-03-08 | 90   |
|  3 |          1 | Mat       | 2016-03-09 | 80   |
|  4 |          2 | Tom       | 2016-03-09 | 100  |
|  5 |          1 | Mat       | 2016-03-10 | null |
|  6 |          2 | Tom       | 2016-03-10 | null |
+----+------------+-----------+------------+------+
Run Code Online (Sandbox Code Playgroud)

注意:打开2016-03-10 Mat并且Tom不需要工作。因此,它们的值在最终结果中应该为空。在这种情况下,该performance表将没有 Mat 和 Tom 的条目2016-03-10

我对如何实现这一目标有点迷茫。

Jul*_*eur 6

你必须CROSS JOINUsers你的日历查询表。

它将为您提供每个用户的每个日期之一的结果:

selected_date | firstname
2016-03-08    | Mat
2016-03-09    | Mat
2016-03-10    | Mat
2016-03-11    | Mat
2016-03-08    | Tom
2016-03-09    | Tom
2016-03-10    | Tom
2016-03-11    | Tom
Run Code Online (Sandbox Code Playgroud)

这然后可以LEFT JOINPerformance表。( SQL 小提琴)

询问:

SELECT u.id, u.firstname, cal.selected_date, p.val
FROM Users u
CROSS JOIN (
    SELECT selected_date FROM (
        SELECT adddate('1970-01-01',t4.i*10000 + t3.i*1000 + t2.i*100 + t1.i*10 + t0.i) selected_date 
        from            
            (SELECT 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t0,
            (SELECT 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t1,
            (SELECT 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t2,
            (SELECT 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t3,
            (SELECT 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t4
    ) v
    WHERE selected_date BETWEEN '2016-03-08' AND '2016-03-11'
) cal
LEFT JOIN performance p
    ON u.id = p.employeeId AND cal.selected_date = p.date;
Run Code Online (Sandbox Code Playgroud)

输出:

 id | firstname | selected_date |    val 
  1 |       Mat |    2016-03-08 |    100 
  2 |       Tom |    2016-03-08 |     90 
  1 |       Mat |    2016-03-09 |     80 
  2 |       Tom |    2016-03-09 |    100 
  1 |       Mat |    2016-03-10 | (null) 
  2 |       Tom |    2016-03-10 | (null) 
  1 |       Mat |    2016-03-11 | (null) 
  2 |       Tom |    2016-03-11 | (null) 
Run Code Online (Sandbox Code Playgroud)