Mysql - 用多个连接表查找缺失日期

4
我需要一些帮助来编写一个mysql查询。我需要查找给定日期范围内特定业务id / 项目id的所有未完成报告。
基本上,对于给定的业务id,我需要知道项目的名称以及所有缺少报告或未标记为已完成的日期。
我正在使用日历表技巧(如此处此处所述)来查找缺失的报告日期,但我在连接项目表以查找错过报告的关联项目/业务方面遇到了问题。
我基本上需要一个结果集,它将为我提供类似于此类数据的数据:
+------------+-----------+--------------+
| project_id | name      | missing_date |
+------------+-----------+--------------+
| 1          | Project 1 | 2014-01-01   |
| 1          | Project 1 | 2014-01-03   |
| 1          | Project 1 | 2014-01-04   |
| 1          | Project 1 | 2014-01-07   |
| 1          | Project 1 | 2014-01-09   |
| 2          | Project 2 | 2014-01-02   |
| 2          | Project 2 | 2014-01-03   |
| 2          | Project 2 | 2014-01-04   |
+------------+-----------+--------------+

这是我的模式:
projects table:
+----------------+------------------+------+-----+-------------------+----------------+
| Field          | Type             | Null | Key | Default           | Extra          |
+----------------+------------------+------+-----+-------------------+----------------+
| project_id     | int(10) unsigned | NO   | PRI | NULL              | auto_increment |
| business_id    | int(10) unsigned | NO   | MUL | NULL              |                |
| name           | tinytext         | YES  |     | NULL              |                |
+----------------+------------------+------+-----+-------------------+----------------+

reports table:
+---------------------+------------------+------+-----+-------------------+----------------+
| Field               | Type             | Null | Key | Default           | Extra          |
+---------------------+------------------+------+-----+-------------------+----------------+
| report_id           | int(10) unsigned | NO   | PRI | NULL              | auto_increment |
| project_id          | int(10) unsigned | NO   | MUL | NULL              |                |
| report_date         | date             | NO   | MUL | NULL              |                |
| completed           | bit(1)           | NO   |     | b'0'              |                |
+---------------------+------------------+------+-----+-------------------+----------------+


calendar table:
+--------------+-------------+------+-----+---------+-------+
| Field        | Type        | Null | Key | Default | Extra |
+--------------+-------------+------+-----+---------+-------+
| dt           | date        | NO   | PRI | NULL    |       |
| month_name   | varchar(9)  | YES  |     | NULL    |       |
| day_name     | varchar(9)  | YES  |     | NULL    |       |
| y            | smallint(6) | YES  |     | NULL    |       |
| q            | tinyint(4)  | YES  |     | NULL    |       |
| m            | tinyint(4)  | YES  |     | NULL    |       |
| d            | tinyint(4)  | YES  |     | NULL    |       |
| dw           | tinyint(4)  | YES  |     | NULL    |       |
| w            | tinyint(4)  | YES  |     | NULL    |       |
| is_weekday   | bit(1)      | YES  |     | NULL    |       |
| is_holiday   | bit(1)      | YES  |     | NULL    |       |
| holiday_desc | varchar(32) | YES  |     | NULL    |       |
+--------------+-------------+------+-----+---------+-------+

以下查询可以返回未完成报告的列表,但我仍然需要填补其中没有报告记录的日期间隙。
select 
    p.project_id,
    p.name,
    c.dt as missing_date,
    r.completed
from reports r
join projects p on (r.project_id = p.project_id)
right join calendar c on (c.dt = r.report_date)
where c.dt >= '2014-02-01'
and c.dt <= '2014-02-10'
-- and r.report_date is null /** THE RESULT SET IS EMPTY IF I UNCOMMENT THIS **/
and r.completed = false
and c.is_holiday = false
and c.is_weekday = true
and p.business_id = 1001
order by p.project_id, r.report_date, c.dt;

任何帮助都将不胜感激!

你的查询结果是什么,为什么要使用右连接到日历表? - Christian Ammer
我得到了一个空的结果集。 我需要加入日历表,以便确定应该在哪些日期创建报告。 - elprogrammador
我不认为需要使用右连接,为什么要包括所有日历记录而不匹配报告记录呢? - Christian Ammer
你可以尝试拆分查询并检查子查询的结果:A:“没有连接且仅包含日期的日历”,B:“没有连接且带有完整where语句的日历”,C:“报告连接日历”... - Christian Ammer
2个回答

0

我阅读了您提供的链接,这种日期存储方法很棒。 在您的查询中使用了以下方式:

right join calendar c on (c.dt = r.report_date)

但我在您的报表中没有看到report_date。我建议您检查一下是否因为这个问题,因为除此之外,您的查询似乎正常工作。


抱歉,报告表中确实没有report_date列。我在发布示例模式时不小心将其删除了。我已经编辑了示例模式以显示它现在已经存在。 - elprogrammador

0

好的,我终于让它工作了。这是一个相当复杂的查询,需要在项目表上进行内部连接,但我不知道有更好的方法来做到这一点 - 我是一个Java程序员,这些天过于依赖Hibernate来构建我的查询 :). 如果有人有更有效的解决方案,我全听着!

最终查询:

select 
    p.project_id,
    p.name,
    c.dt as missing_date,
    r.report_date,
    r.completed
from calendar c
inner join (
    select 
        p1.project_id,
        p1.name
    from projects p1
    where p1.project_id = 1005
    -- where p1.business_id = 1001 /** OR USE THE BUSINESS ID **/

) p on c.dt between '2014-02-01' and '2014-02-28'
left join reports r on r.report_date = c.dt
and r.project_id = p.project_id
and r.completed = false
where (r.report_date is null or r.completed = false)
and c.is_holiday = false
and c.is_weekday = true
order by p.project_id, c.dt;

生成正确的结果:

+------------+--------------+--------------+-------------+-----------+
| project_id | name         | missing_date | report_date | completed |
+------------+--------------+--------------+-------------+-----------+
|       1005 | Project 1005 | 2014-02-03   | 2014-02-03  |         0 |
|       1005 | Project 1005 | 2014-02-04   | 2014-02-04  |         0 |
|       1005 | Project 1005 | 2014-02-05   | NULL        |      NULL |
|       1005 | Project 1005 | 2014-02-06   | 2014-02-06  |         0 |
|       1005 | Project 1005 | 2014-02-07   | NULL        |      NULL |
|       1005 | Project 1005 | 2014-02-10   | 2014-02-10  |         0 |
|       1005 | Project 1005 | 2014-02-11   | 2014-02-11  |         0 |
|       1005 | Project 1005 | 2014-02-12   | 2014-02-12  |         0 |
|       1005 | Project 1005 | 2014-02-13   | NULL        |      NULL |
|       1005 | Project 1005 | 2014-02-14   | NULL        |      NULL |
|       1005 | Project 1005 | 2014-02-18   | NULL        |      NULL |
|       1005 | Project 1005 | 2014-02-19   | NULL        |      NULL |
|       1005 | Project 1005 | 2014-02-20   | 2014-02-20  |         0 |
|       1005 | Project 1005 | 2014-02-21   | 2014-02-21  |         0 |
|       1005 | Project 1005 | 2014-02-24   | 2014-02-24  |         0 |
|       1005 | Project 1005 | 2014-02-25   | 2014-02-25  |         0 |
|       1005 | Project 1005 | 2014-02-26   | NULL        |      NULL |
|       1005 | Project 1005 | 2014-02-27   | NULL        |      NULL |
|       1005 | Project 1005 | 2014-02-28   | NULL        |      NULL |
+------------+--------------+--------------+-------------+-----------+

谢谢大家的帮助!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接