2014-02-27 48 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