2014-02-27 81 views
4

我需要一些帮助来编写mysql查询。我需要为特定的商家ID /项目ID查找给定日期范围内的所有错过的报告。Mysql - 用多个连接表查找缺失日期

基本上,对于给定的业务ID,我需要知道项目名称以及报告缺失或未标记为已完成的所有日期。

我现在用的是日历表伎俩(如描述herehere)寻找失踪的报告日期,但我有加入本项目表问题找相关的项目/企业一个报告错过了。

基本上,我需要的结果集,这将使我类似这样的数据:

+------------+-----------+--------------+ 
| 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; 

任何帮助将不胜感激!

+0

查询的结果是什么以及为什么要正确加入日历表? –

+0

我得到一个空的结果集。我需要加入日历表,以便确定报告应该创建的所有日期。 – elprogrammador

+0

我没有看到** right **加入的必要性,为什么包含所有*日历*记录而没有匹配*报告*记录? –

回答

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 | 
+------------+--------------+--------------+-------------+-----------+ 

感谢您的帮助球员和加尔斯!

0

我阅读了您提供的链接,这种日期存储方法非常棒。 在您的查询,无论如何你使用:

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

,但我没有看到你的报告表中的任何REPORT_DATE。 我建议你检查一下,如果问题是因为它,因为除了你的查询似乎正常工作。

+0

对不起,报表包含report_date列。我在发布示例架构时意外删除了它。我编辑了示例模式以显示它现在在那里。 – elprogrammador