2012-11-22 67 views
2

我有3個表設置這樣的(有點簡化):SQL連接3個表(基於2條規定 - ?)

time_tracking:ID,tr_proj_id,tr_min,tr_type
time_projects:ID,PROJECT_NAME
time_tasks :ID,TASK_NAME

基本上,我想要檢索基於tr_type要麼PROJECT_NAMETASK_NAME它可以是有價值的 「項目」 或 「任務」

一個例子

time_tracking

+----+------------+--------+---------+ 
| id | tr_proj_id | tr_min | tr_type | 
+----+------------+--------+---------+ 
| 1 |   3 |  60 | project | 
| 2 |   3 | 360 | task | 
| 3 |   1 | 120 | project | 
| 4 |   2 |  30 | project | 
| 5 |   2 |  30 | task | 
| 6 |   1 |  90 | task | 
+----+------------+--------+---------+ 

time_projects

+----+------------------------+ 
| id |  project_name  | 
+----+------------------------+ 
| 1 | Make someone happy  | 
| 2 | Start a project  | 
| 3 | Jump out of the window | 
+----+------------------------+ 

time_tasks

+----+---------------------+ 
| id |  task_name  | 
+----+---------------------+ 
| 1 | drink a beer  | 
| 2 | drink a second beer | 
| 3 | drink more   | 
+----+---------------------+ 

所需的輸出

+----+------------------------+------------+--------+---------+ 
| id |   name   | tr_proj_id | tr_min | tr_type | 
+----+------------------------+------------+--------+---------+ 
| 1 | Jump out of the window |   3 |  60 | project | 
| 2 | drink more    |   3 | 360 | task | 
| 3 | Make someone happy  |   1 | 120 | project | 
| 4 | Start a project  |   2 |  30 | project | 
| 5 | drink a second beer |   2 |  30 | task | 
| 6 | drink a beer   |   1 |  90 | task | 
+----+------------------------+------------+--------+---------+ 

而處於全真不好JOIN的事情,這是我想出來的,到目前爲止的唯一的事情(不工作..):

SELECT tt.tr_proj_id, tt.tr_type, tt.tr_min, pp.project_name, pp.id, ta.task_name, ta.id 
FROM time_tracking as tt, time_projects as pp, time_tasks as ta 
WHERE ((tt.tr_type = 'project' AND pp.id = tt.tr_proj_id) OR (tt.tr_type = 'task' AND ta.id = tt.tr_proj_id)) 
AND tt.tr_min > 0 
ORDER BY tt.tr_proj_id DESC 

如果任何人有關於如何做到這一點的想法,請隨時分享!
謝謝!


更新:貌似我忘了指定我使用的是訪問數據庫。這顯然不接受的東西,如CASE或​​3210 ..顯然有IIF(),但我不太清楚如何在這種情況下使用它。

+1

這是爲什麼工作? '2 |喝更多| 3 | 360 |任務' –

+0

期望的輸出是難以理解的,「發送電子郵件」在哪裏? –

+0

@HamletHakobyan我的不好,你是對的,我編輯糾正輸出 – Phil

回答

0

試試這個:

SELECT 
    tt.id, 
    CASE WHEN tt.tr_type = 'project' THEN pp.project_name 
     WHEN tt.tr_type = 'task' THEN ta.task_name END as name, 
    tt.tr_proj_id, 
    tt.tr_type, 
    tt.tr_min, 
FROM time_tracking as tt 
    left join time_projects as pp on pp.id = tt.tr_proj_id 
    left join time_tasks as ta on ta.id = tt.tr_proj_id 
WHERE tt.tr_min > 0 
ORDER BY tt.tr_proj_id DESC 
+0

在這種情況下使用Access,我用'IIf()'替換了'CASE',它實現了訣竅! 'SELECT tt.id,IIf([tt.tr_type] ='project',[pp.project_name],[ta.task_name])作爲名稱,tt.tr_proj_id等。 – Phil

2

使用join子句和WHERE子句中的移動你的加入條件爲on條款:

SELECT 
    tt.tr_proj_id, 
    tt.tr_type, 
    tt.tr_min, 
    pp.project_name, 
    pp.id, 
    ta.task_name, 
    ta.id 
FROM time_tracking as tt 
left join time_projects as pp on tt.tr_type = 'project' AND pp.id = tt.tr_proj_id 
left join time_tasks as ta on tt.tr_type = 'task' AND ta.id = tt.tr_proj_id 
WHERE tt.tr_min > 0 
ORDER BY tt.tr_proj_id DESC,tt.tr_day ASC 

我用left join,它給你從主表中的一行,即使不存在對於參加(你所加入的表列從空,如果沒有加入)


的一個關鍵點在這裏,許多SQL程序員沒有意識到,就是ON子句可以包含任何康迪即使不是來自聯結表(如本例中)。許多程序員認爲條件只能是與正式的外鍵關係相關的條件。

0

兩個執行工會加入:

select tt.id, tp.project_name name, tt.tr_proj_id, tt.tr_min, tt.tr_type 
    from time_tracking tt 
     inner join time_projects tp on tp.id = tt.tr_proj_id 
where tt.tr_type = 'project' 
union all 
select tt.id, tp.project_name name, tt.tr_proj_id, tt.tr_min, tt.tr_type 
    from time_tracking tt 
     inner join time_tasks tk on tk.id = tt.tr_proj_id 
where tt.tr_type = 'task' 

這將會給你確切的結果見表你想

0
SELECT 
    time_tracking.id, 
    time_tracking.tr_min, 
    time_tracking.tr_type, 
    coalesce(time_projects.project_name, time_tasks.task_name) as name 
FROM time_tracking 
LEFT OUTER JOIN time_projects on time_projects.id = time_tracking.tr_proj_id AND time_tracking.tr_type = 'project' 
LEFT OUTER JOIN time_tasks on time_tasks.id = time_tracking.tr_proj_id AND time_tracking.tr_type = 'task' 
WHERE time_tracking.tr_min > 0 
ORDER BY time_tracking.id DESC -- ... 

​​3210是MSSQL,有相當於ISNULL和這樣的其他數據庫技術

這個想法是你加入到表中,如果加入失敗,你會得到NULL連接失敗。然後您使用COALESCE來挑選出成功的連接值。