2011-04-22 54 views
1

這是代碼,顯示輸入和所需的輸出。如何將此查詢寫爲完整聯接而不是聯合左/右聯接?

基本上,我試圖自我加入,以將我的經紀人聲明的結果與我的內部記錄進行匹配。所以左邊的一列是經紀人的名單,右邊是我的名單。如果經紀人有一個職位,而我沒有,則在右邊是NULL。如果我有一個職位,經紀人沒有,左邊是NULL。

左連接+右連接+聯合完全按照我的意願工作。似乎應該有一些巫術,讓一個完整的加入,沒有兩個選擇,但我無法弄清楚。

drop table MatchPositions 
go 

create table MatchPositions 
( 
    mt_source varchar (10), 
    mt_symbol varchar (10), 
    mt_qty float, 
    mt_price float 
) 

go 

insert into MatchPositions values ('BROKER', 'IBM', 100, 50.25) 
insert into MatchPositions values ('BROKER', 'MSFT', 75, 30) 
insert into MatchPositions values ('BROKER', 'GOOG', 25, 500) 
insert into MatchPositions values ('BROKER', 'SPY', 200, 113) 

insert into MatchPositions values ('MODEL', 'MSFT', 75, 30) 
insert into MatchPositions values ('MODEL', 'GOOG', 25, 500) 
insert into MatchPositions values ('MODEL', 'GLD', 300, 150) 

go 

select * from MatchPositions b 
left join MatchPositions m on b.mt_symbol = m.mt_symbol and m.mt_source = 'MODEL' 
where b.mt_source = 'BROKER' 
union 

select * from MatchPositions b 
right join MatchPositions m on b.mt_symbol = m.mt_symbol and b.mt_source = 'BROKER' 
where m.mt_source = 'MODEL' 

和這裏的預期輸出:

mt_source mt_symbol mt_qty     mt_price    mt_source mt_symbol mt_qty     mt_price 
---------- ---------- ---------------------- ---------------------- ---------- ---------- ---------------------- ---------------------- 
NULL  NULL  NULL     NULL     MODEL  GLD  300     150 
BROKER  GOOG  25      500     MODEL  GOOG  25      500 
BROKER  IBM  100     50.25     NULL  NULL  NULL     NULL 
BROKER  MSFT  75      30      MODEL  MSFT  75      30 
BROKER  SPY  200     113     NULL  NULL  NULL     NULL 
+0

你使用的是什麼版本的sql? – Dave 2011-04-22 18:49:27

回答

4
;WITH T1 AS 
(
SELECT * 
FROM MatchPositions 
WHERE mt_source = 'BROKER' 
), T2 AS 
(
SELECT * 
FROM MatchPositions 
WHERE mt_source = 'MODEL' 
) 
SELECT * 
FROM T1 FULL JOIN T2 ON T1.mt_symbol = T2.mt_symbol 
+0

CTEs,當然! (捂臉)。謝謝,這也解決了更普遍的情況(我沒有發佈),表格更復雜一些,把東西放在'where'與'join'之間,在存在NULL的時候會變得很冒險。您的解決方案修復了所有這些問題。 – 2011-04-22 19:29:22

0

如果您的RDBMS支持FULL JOIN(也稱爲FULL OUTER JOIN):

SELECT * 
FROM (SELECT * FROM MatchPositions WHERE mt_source = 'BROKER') b 
FULL 
JOIN (SELECT * FROM MatchPositions WHERE mt_source = 'MODEL') m 
    ON b.mt_symbol = m.mt_symbol 

該解決方案是基本相同作爲Martin的,只是使用了不同的語法,這可能會有助於您的RDBMS不支持CTE。

+0

返回4行而不是5與OP的數據(它不包括在所需的輸出頂部的NULL) – 2011-04-22 18:54:55

+0

@Martin:修復,感謝您的注意。 – 2011-04-22 19:02:03

+0

討厭這個給你,但它現在返回9行! – 2011-04-22 19:12:00

1

可能使用ISNULL函數:

SELECT * 
FROM MatchPositions b 
    FULL JOIN MatchPositions m on b.mt_symbol = m.mt_symbol 
          and b.mt_source != m.mt_source 
WHERE isnull(b.mt_source, 'BROKER') = 'BROKER' 
    and isnull(m.mt_source, 'MODEL') = 'MODEL' 
+0

幾乎是正確的,但是將'mt_source'列封裝在一個函數中否定了任何可能的索引使用。看到下面更好的方法。 – 2011-04-22 19:38:06

0
SELECT * 
FROM MatchPositions b 
    FULL JOIN MatchPositions m ON b.mt_symbol = m.mt_symbol 
          AND b.mt_source = 'BROKER' 
          AND m.mt_source = 'MODEL' 

此過濾表進入 'BROKER' 和連接它們之前外 '模式' 的部分。

+0

返回12行不是所需的5(如此處所示http://data.stackexchange.com/stackoverflow/q/98523/) – 2011-04-22 19:25:31

+0

我承認不先測試它。對於那個很抱歉。尼斯鏈接BTW。 – Neil 2011-04-22 19:39:25

0

試試這個:

select * 
from  MatchPositions broker 
full join MatchPositions model on model.mt_symbol = broker.mt_symbol 
           and model.mt_source <> broker.mt_source 
where (broker.mt_source = 'BROKER' or broker.MT_SOURCE is null) 
    and (model.mt_source = 'MODEL' or model.MT_SOURCE is null) 

從第一個邏輯源表,你想要麼經紀行或缺少的行。

從第二個邏輯源表中,您需要模型行或缺少行。