我不知道如何创建一个SQL语句来连接4个表
1)供应商表将始终匹配供应商#
上每个表的条目
2)其余3个中的每一个将由供应商#& amp; Seq#
3)3的任何组合都可以有数据(或没有)
4)我不想从供应商表中选择,除非我至少得到3个中的一个
供应商
Vendor # Name
-------- ----
1 Tom Smith
2 Bruce Lee
3 Seamus O’Leary
4 Jonathan Stewart
5 Benjamin Franklin
选择月份范围
Vendor # Seq # MonthFrom MonthTo
-------- ----- --------- -------
1 1 3 6
1 2 7 9
3 2 5 6
选择周
Vendor # Seq # Week #
-------- ----- ------
1 1 3
3 1 4
4 1 1
选择日期
Vendor # Seq # Day #
1 1 15
1 2 25
2 1 12
4 1 05
5 1 19
所需表格(已加入)
Vendor# Name Seq# MonthFrom MonthTo Week# Day#
1 Tom Smith 1 3 6 3 15
1 Tom Smith 2 7 9 NULL 25
2 Bruce Lee 1 NULL NULL NULL 12
3 Seamus O’Leary 1 NULL NULL 4 NULL
3 Seamus O’Leary 2 5 6 NULL NULL
4 Jonathan Stewart 1 NULL NULL 1 05
5 Benjamin Franklin 1 NULL NULL NULL 19
诀窍是3中的任何一个(不包括'供应商')可以或不可以拥有数据,我只想要返回一行,如果有来自3个中的一个或多个的东西。
任何建议?
答案 0 :(得分:1)
要在Vendor和Seq上加入,我们首先需要拥有所有可能的组合。然后我们可以根据这些组合过滤表格。我在SQL服务器上运行了以下命令:
<强>设置强>
.n2-font-d7df9860b9d2e958d0b5b8dadd6b6bd5-paragraph{
font-family:'HelveticaNeue', 'Helvetica Neue', serif !important;
}
<强>查询强>
declare @Vendors table(id int, name varchar(20));
declare @MonthRangeSelected table (vendor int, seq int null, monthFrom int null, monthTo int null);
declare @WeekSelected table (vendor int, seq int null, week int null);
declare @DaySelected table (vendor int, seq int null, day int null);
insert into @Vendors
select 1, 'Tom Smith'
union all
select 2, 'Bruce Lee'
union all
select 3, 'Seamus O’Leary'
union all
select 4, 'Jonathan Stewart'
union all
select 5, 'Benjamin Franklin';
insert into @MonthRangeSelected
select 1, 1, 3, 6
union all
select 1, 2, 7, 9
union all
select 3, 2, 5, 6;
insert into @WeekSelected
select 1, 1, 3
union all
select 3, 1, 4
union all
select 4, 1, 1;
insert into @DaySelected
select 1, 1, 15
union all
select 1, 2, 25
union all
select 2, 1, 12
union all
select 4, 1, 05
union all
select 5, 1, 19;
这就是结果:
select v.Id, v.name, combinations.seq, MonthFrom, MonthTo, Week, Day
from @Vendors v
inner join (select m.vendor, m.seq
from @MonthRangeSelected m
union
select w.vendor, w.seq
from @WeekSelected w
union
select d.vendor, d.seq
from @DaySelected d) combinations
on combinations.vendor = v.id
left join @MonthRangeSelected m
on m.Vendor = combinations.vendor
and m.seq = combinations.seq
left join @WeekSelected w
on w.Vendor = combinations.vendor
and w.seq = combinations.seq
left join @DaySelected d
on d.Vendor = combinations.vendor
and d.seq = combinations.seq
where (MonthFrom is not null
or MonthTo is not null
or Week is not null
or Day is not null)
答案 1 :(得分:1)
这比听起来更复杂。根据结果,当表中有多个匹配项时,您不需要笛卡尔积。所以,你需要考虑seqnum。
select v.Vendor, v.name, coalesce(m.seq, w.seq, d.seq) as Seq,
m.MonthFrom, m.MonthTo, w.Week, d.Day
from Vendors v left join
SMonthRangeSelected m
on v.Vendor = m.Vendor full join
WeekSelected w
on v.Vendor = w.Vendor and m.seq = w.seq full join
DaySelected d
on v.Vendor = d.Vendor and d.seq in (w.seq, m.seq)
where m.Vendor is not null or
w.Vendor is not null or
d.Vendor is not null;
使用full join
时会发生奇怪的事情,特别是如果您想要进行任何过滤。另一种方法使用union all
和group by
:
select mwd.Vendor, v.name, mwd.seq,
max(MonthFrom) as MonthFrom, max(MonthTo) as monthTo,
max(Week) as week, max(Day) as day
from ((select m.Vendor, m.seq, m.MonthFrom, m.MonthTo, NULL as week, NULL as day
from month m
) union all
(select w.Vendor, w.seq, NULL as MonthFrom, NULL as MonthTo, w.week, NULL as day
from week
) union all
(select d.Vendor, d.seq, NULL as MonthFrom, NULL as MonthTo, NULL as week, d.day
from day d
)
) mwd join
Vendor v
on v.vendor = vmwd.vendor
group by mwd.Vendor, v.vname, mwd.seq;
请注意,此版本不需要Vendor
表。
答案 2 :(得分:0)
您应该将外部联接留给3个表中的每个表,然后在where子句中包含以下内容:
(MonthFrom is not null or Week# is not null or Day# is not null)
听起来你可以内部加入供应商表
答案 3 :(得分:0)
您需要在三个表上进行完全外连接,以便获得所有供应商和序列号组合。加入这些与供应商,你就完成了:
select vendorno, v.name, x.seqno, x.monthfrom, x.monthto, x.weekno, x.dayno
from vendor v
join
(
select vendorno, seqno, m.monthfrom, m.monthto, w.weekno, d.dayno
from monthsel m
full outer join weeksel w using (vendorno, seqno)
full outer join daysel d using (vendorno, seqno)
) x using(vendorno)
order by vendorno, x.seqno;
UPDATE:如果没有USING子句,相同的查询会变得非常笨拙且可读性更低:
select v.vendorno, v.name, x.seqno, x.monthfrom, x.monthto, x.weekno, x.dayno
from vendor v
join
(
select
coalesce(m.vendorno, w.vendorno, d.vendorno) as vendorno,
coalesce(m.seqno, w.seqno, d.seqno) as seqno,
m.monthfrom, m.monthto, w.weekno, d.dayno
from monthsel m
full outer join weeksel w
on (w.vendorno = m.vendorno or w.vendorno is null or m.vendorno is null)
and (w.seqno = m.seqno or w.seqno is null or m.seqno is null)
full outer join daysel d
on (d.vendorno = m.vendorno or d.vendorno is null or m.vendorno is null)
and (d.vendorno = w.vendorno or d.vendorno is null or w.vendorno is null)
and (d.seqno = m.seqno or d.seqno is null or m.seqno is null)
and (d.seqno = w.seqno or d.seqno is null or w.seqno is null)
) x on x.vendorno = v.vendorno
order by v.vendorno, x.seqno;
(希望我没有在这里混淆。通过这样的查询很容易复制和粘贴错误。所以如果它不能正常工作,请注意拼写错误。)
答案 4 :(得分:0)
我相信这会做你需要的:
SELECT
V.[Vendor#], -- I'll never understand why people insist on using names that require brackets
V.Name,
COALESCE(M.[Seq#], W.[Seq#], D.[Seq#]) AS [Seq#],
M.MonthFrom,
M.MonthTo,
W.[Week#],
D.[Day#]
FROM
Vendor V
LEFT OUTER JOIN MonthRange M ON M.[Vendor#] = V.[Vendor#]
LEFT OUTER JOIN Week W ON W.[Vendor#] = V.[Vendor#]
LEFT OUTER JOIN Day D ON D.[Vendor#] = V.[Vendor#]
WHERE
(
M.[Vendor#] IS NOT NULL OR
W.[Vendor#] IS NOT NULL OR
D.[Vendor#] IS NOT NULL
) AND
(M.[Seq#] = W.[Seq#] OR M.[Seq#] IS NULL OR W.[Seq#] IS NULL) AND
(M.[Seq#] = D.[Seq#] OR M.[Seq#] IS NULL OR D.[Seq#] IS NULL) AND
(D.[Seq#] = W.[Seq#] OR D.[Seq#] IS NULL OR W.[Seq#] IS NULL)