如何将此查询编写为完整联接而不是联合左/右联接?

时间:2011-04-22 18:43:25

标签: sql join union

这是代码,显示输入和所需输出。

基本上,我正在尝试自我加入,以便将我的经纪人声明的结果与我的内部记录相匹配。所以左边的列是经纪人的列表,右边是我的列表。如果经纪人有一个仓位,而我没有,则右边是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

5 个答案:

答案 0 :(得分: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

答案 1 :(得分: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'

答案 2 :(得分: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,这可能会有所帮助。

答案 3 :(得分: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”和“MODEL”部分。

答案 4 :(得分: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 )

从第一个逻辑源表中,您需要代理行或缺少行。

从第二个逻辑源表中,您需要模型行或缺少行。