我正在尝试加入3个表,其中第三个表包含对第二个表和第一个表的引用;我想要这些引用中的任何一个的结果。但是,在第三个表引用第一个表的情况下,我不需要第二个表的结果。
这很难解释,所以我用下面的例子说明了我的意思。
第一个select语句产生6行;我理解为什么,但那不是我追求的目标。
第二个2给出了我追求的结果,但是它们有一个代码味道。任何人都可以建议更好的方法来实现相同的输出吗?
另请参阅SQL小提琴:http://sqlfiddle.com/#!3/8029cc/1
--code to setup my example
declare @t1 table (id bigint, val nvarchar(10))
declare @t2 table (id bigint, t1Id bigint, val2 nvarchar(10))
declare @t3 table (id bigint, t1Id bigint, t2Id bigint, val3 nvarchar(10))
insert @t1 (id, val) values (1, '1.1')
insert @t2 (id, t1Id, val2)
values (1, 1, '2.1')
,(2, 1, '2.2')
,(3, 1, '2.3')
insert @t3 (id, t1Id, t2Id, val3)
values (1, 1, null, 'XXX')
, (1, null, 1, '3.1')
,(2, null, 2, '3.2')
,(3, null, 3, '3.3')
--this produces 6 results; I only want 4
select *
from @t1 t1
left outer join @t2 t2
on t2.t1Id = t1.Id
left outer join @t3 t3
on t3.t2Id = t2.Id
or t3.t1Id = t1.id
--this works, but means repeating myself; which I'd prefer not to do if possible (could use a cte to make that simpler in the real world scenario, but still not ideal)
select t1.id, t2.id, t3.id, t1.val, t2.val2, t3.val3
from @t1 t1
left outer join @t2 t2
on t2.t1Id = t1.Id
left outer join @t3 t3
on t3.t2Id = t2.Id
union all
select t1.id, null, t3.id, t1.val, null, t3.val3
from @t1 t1
left outer join @t3 t3
on t3.t1Id = t1.id
--this works too, but feels very hacky
select t1.id, t2.id, t3.id, t1.val, t2.val2, t3.val3
from @t1 t1
left outer join
(
select id, t1id, val2
from @t2
union all
select null, null, null
) t2
on coalesce(t2.t1Id,t1.Id) = t1.Id
left outer join @t3 t3
on t3.t2Id = t2.Id
or (t3.t1Id = t1.id and t2.Id is null)
更新
我只是想到了另一个比上面那些感觉更清洁的解决方案;虽然我对它有点不舒服......
--another option; again slightly hacky
select id, id2, id3, val, val2, val3
from
(
select t1.id
, case when t3.t1Id = t1.id then null else t2.id end id2
, t3.id id3
, t1.val
, case when t3.t1Id = t1.id then null else t2.val2 end val2
, t3.val3
, row_number() over (partition by t1.id order by case when t3.t1Id = t1.id then null else t2.id end, t3.id) x
from @t1 t1
left outer join @t2 t2
on t2.t1Id = t1.Id
left outer join @t3 t3
on t3.t2Id = t2.Id
or t3.t1Id = t1.id
) t
where id2 is not null or x = 1
答案 0 :(得分:1)
也许我没有完全理解你的要求/输出。
但是,查询应该具有相同的结果
SELECT *
FROM t3
LEFT JOIN t2
ON t2.id = t3.t2Id
LEFT JOIN t1
ON t3.t1Id = t1.id
AND t2.id IS NULL
答案 1 :(得分:1)
尝试此查询,它将产生与上一个查询相同的输出结果:
SELECT T.ID,
CASE WHEN T3.t2Id IS NULL THEN NULL ELSE T.T2ID END AS T2ID,
T3.id AS T3ID,
T.VAL,
CASE WHEN T3.t2Id IS NULL THEN NULL ELSE T.VAL2 END AS VAL2,
T3.VAL3
FROM (SELECT T1.id,
T1.val,
T2.Id AS T2ID,
T2.val2
FROM @t1 AS T1 JOIN @t2 AS T2
ON T1.id = T2.t1id
) AS T JOIN @t3 AS T3
ON T.T2ID = T3.ID
ORDER BY T3.VAL3
<强> test is here 强>
输出结果
答案 2 :(得分:1)
非常简单 - 你的错误是你的起点。 从表3开始,然后连接到其他人 - 然后添加where条件。 即。
SELECT * FROM @t3
LEFT OUTER JOIN @t1
ON [@t1].id = [@t3].t1id
LEFT OUTER JOIN @t2
ON [@t2].id = [@t3].t2id
WHERE [@t1].id IS NOT NULL
OR ( [@t2].id IS NOT NULL AND [@t1].id IS NULL)