2013-09-30 114 views
3

我有兩個表,其中有些列相似,有些不同。我需要返回一個結果,將不同的列合併到一個結果集中,但是,我需要一個可能導致兩個表中沒有匹配的條件,我嘗試了一個聯合,但是返回了兩個空值的行,並且我只想要一個。這裏有兩個例子表:當任一表可能返回零結果時,SQL從多個表中返回一個結果集

TableA 
---------------------------------------------------- 
| ID | ColumnA | ColumnB | ForeignKeyA | TimeStamp | 
---------------------------------------------------- 
| 1 | Val1 | Val2 | KeyA  | 2013-01-01| 
---------------------------------------------------- 
| 2 | Val3 | Val4 | KeyB  | 2013-01-02| 
---------------------------------------------------- 

TableB 
------------------------------------------ 
| ID | ColumnC | ForeignKeyA | TimeStamp | 
------------------------------------------ 
| 1 | Val5 | KeyA  | 2013-01-01| 
------------------------------------------ 
| 2 | Val6 | KeyC  | 2013-01-02| 
------------------------------------------ 

這裏是一些僞查詢和返回值,我想:

1)

SELECT TableA.ColumnA AS ColumnA, 
TableA.ColumnB AS Column B, 
TableB.ColumnC AS ColumnC, 
TableA.id AS TableA_ID, 
TableB.id AS TableB_ID 
(WHERE ForeignKeyA in either table = KeyA and TimeStamp in either table = 2013-01-01) 

>> 
------------------------------------------------------- 
| ColumnA | ColumnB | ColumnC | TableA_ID | TableB_ID | 
------------------------------------------------------- 
| Val1 | Val2 | Val5 | 1   | 1   | 
------------------------------------------------------- 

2)

SELECT TableA.ColumnA AS ColumnA, 
TableA.ColumnB AS Column B, 
TableB.ColumnC AS ColumnC, 
TableA.id AS TableA_ID, 
TableB.id AS TableB_ID 
(WHERE ForeignKeyA in either table = KeyB and TimeStamp in either table = 2013-01-02) 

>> 
------------------------------------------------------- 
| ColumnA | ColumnB | ColumnC | TableA_ID | TableB_ID | 
------------------------------------------------------- 
| Val3 | Val4 | Null | 2   | Null  | 
------------------------------------------------------- 

3 )

SELECT TableA.ColumnA AS ColumnA, 
TableA.ColumnB AS Column B, 
TableB.ColumnC AS ColumnC, 
TableA.id AS TableA_ID, 
TableB.id AS TableB_ID 
(WHERE ForeignKeyA in either table = KeyC and TimeStamp in either table = 2013-01-02) 

>> 
------------------------------------------------------- 
| ColumnA | ColumnB | ColumnC | TableA_ID | TableB_ID | 
------------------------------------------------------- 
| Null | Null | Val6 | Null  | 2   | 
------------------------------------------------------- 
+0

你缺少你的僞queires「發件人」條款和你正在尋找將在您的加入語句中找到了解決辦法。我相信你在這裏想要的是一個完整的外連接 – Twelfth

+0

我遺漏了FROM,因爲我不確定實際上應該指定哪個表。我目前正在嘗試一個完整的外部聯接查詢,我沒有得到它的工作,但從您的評論,這聽起來像我可能在正確的軌道上。 – jhummel

+0

你很近。一個內部聯接只返回兩個表中的行,left join將返回'left'表中的所有行(join子句中的第一個),第二個表中沒有找到該記錄的空值。右連接與此相反,完全外連接返回兩個表中的所有行,返回的空值表示在一個表中找到的記錄的空值,而不是其他值。如果您在那裏遇到問題,請發表聲明,我們將幫助您按需要組織表格:) – Twelfth

回答

1

我認爲在你的查詢,你可以使用full outer join像這樣(你可以添加列到on條款,但它會不會改變任何東西):

with 
cteA as (select * from TableA where TimeStamp = _ts and ForeignKeyA = _fk), 
cteB as (select * from TableB where TimeStamp = _ts and ForeignKeyA = _fk) 
select 
    A.ColumnA, A.ColumnB, B.ColumnC, 
    A.ID as TableA_ID, B.ID as TableB_ID 
from cteA as A 
    full outer join cteB as B on 1 = 1 

但是你可以使用full outer join沒有預濾波(這將是低效率的是你有ForeignKeyATimeStamp列的索引):

select 
    A.ColumnA, A.ColumnB, B.ColumnC, 
    A.ID as TableA_ID, B.ID as TableB_ID 
from TableA as A 
    full outer join TableB as B 
     on B.ForeignKeyA = A.ForeignKeyA and B.TimeStamp = A.TimeStamp 
where 
    coalesce(A.ForeignKeyA, B.ForeignKeyA) = _fk and 
    coalesce(A.TimeStamp, B.TimeStamp) = _ts 

sql fiddle demo

+0

小提琴的獎勵積分。工作很好,謝謝! – jhummel

1

這裏可能是棘手的細節是加入對(ForeignKeyA, TimeStamp),而不是作爲ID通常一個人做的。

有了這個簡化的設置(使用合法列名):

CREATE TABLE tbl_a (id int, col_a text, col_b text, fk_a text, ts timestamp); 
INSERT INTO tbl_a VALUES 
    (1, 'Val1', 'Val2', 'KeyA', '2013-01-01') 
,(2, 'Val3', 'Val4', 'KeyB', '2013-01-02'); 

CREATE TABLE tbl_b (id int, col_c text, fk_a text, ts timestamp); 
INSERT INTO tbl_b VALUES 
    (1, 'Val5', 'KeyA', '2013-01-01') 
,(2, 'Val6', 'KeyC', '2013-01-02'); 

查詢將是:

SELECT a.col_a, a.col_b, b.col_c 
     ,a.id AS a_id, b.id AS b_id 
FROM tbl_a a 
FULL JOIN tbl_b b USING (fk_a, ts) 
WHERE 'KeyA' IN (a.fk_a, b.fk_a) 
AND '2013-01-01' IN (a.ts, b.ts); 

應大大低於使用CTE更快。用EXPLAIN ANALYZE進行測試。

-> SQLfiddle demo.