跨三个表的 t-sql 外连接
Posted
技术标签:
【中文标题】跨三个表的 t-sql 外连接【英文标题】:t-sql outer join across three tables 【发布时间】:2011-05-13 18:42:54 【问题描述】:我有三张桌子:
CREATE TABLE person
(id int,
name char(50))
CREATE TABLE eventtype
(id int,
description char(50))
CREATE TABLE event
(person_id int,
eventtype_id int,
duration int)
我想要的是一个单一的查询,它为我提供了每个人的每个事件类型的总持续时间列表,包括所有零条目。例如。如果有 10 个人和 15 种不同的事件类型,则应该返回 150 行,与事件表的内容无关。
我可以让外连接在两个表之间工作(例如,所有事件类型的持续时间),但不能使用第二个外连接。
谢谢!
【问题讨论】:
【参考方案1】:如果您希望 person
和 eventtype
的每个组合都有一行,则建议使用 CROSS JOIN
。要获得我们需要加入event
的持续时间,但这需要是OUTER
加入,因为可能并不总是有一行。您对“total”的使用表明对于person
和event
的给定组合,可能有多个event
,因此我们还需要一个SUM
。
样本数据:
insert person values ( 1, 'Joe' )
insert person values ( 2, 'Bob' )
insert person values ( 3, 'Tim' )
insert eventtype values ( 1, 'Cake' )
insert eventtype values ( 2, 'Pie' )
insert eventtype values ( 3, 'Beer' )
insert event values ( 1, 1, 10 )
insert event values ( 1, 2, 10 )
insert event values ( 1, 2, 5 )
insert event values ( 2, 1, 10 )
insert event values ( 2, 2, 7 )
insert event values ( 3, 2, 8 )
insert event values ( 3, 3, 16 )
insert event values ( 1, 1, 10 )
查询:
SELECT
PET.person_id
, PET.person_name
, PET.eventtype_id
, PET.eventtype_description
, ISNULL(SUM(E.duration), 0) total_duration
FROM
(
SELECT
P.id person_id
, P.name person_name
, ET.id eventtype_id
, ET.description eventtype_description
FROM
person P
CROSS JOIN eventtype ET
) PET
LEFT JOIN event E ON PET.person_id = E.person_id
AND PET.eventtype_id = E.eventtype_id
GROUP BY
PET.person_id
, PET.person_name
, PET.eventtype_id
, PET.eventtype_description
输出:
person_id person_name eventtype_id eventtype_description total_duration
----------- ----------- ------------ --------------------- --------------
1 Joe 1 Cake 20
1 Joe 2 Pie 15
1 Joe 3 Beer 0
2 Bob 1 Cake 10
2 Bob 2 Pie 7
2 Bob 3 Beer 0
3 Tim 1 Cake 0
3 Tim 2 Pie 8
3 Tim 3 Beer 16
Warning: Null value is eliminated by an aggregate or other SET operation.
(9 row(s) affected)
【讨论】:
谢谢 - 这也有效,并且也让我非常清楚这个过程 - 外连接不是我想要的。【参考方案2】:您可以交叉连接人员和事件类型,然后只需将结果连接到事件表:
SELECT
p.Name,
et.Description,
COALESCE(e.duration,0)
FROM
person p
cross join
eventtype et
left join
event e
on
p.id = e.person_id and
et.id = e.eventtype_id
交叉连接是一种交叉连接,对于左表中的每一行,它都连接到右表中的每一行。
【讨论】:
【参考方案3】:您必须在组合中添加CROSS APPLY 才能获得不存在的关系。
SELECT q.name, q.description, SUM(q.Duration)
FROM (
SELECT p.Name, et.description, Duration = 0
FROM person p
CROSS APPLY eventtype et
UNION ALL
SELECT p.Name, et.description, e.duration
FROM person p
INNER JOIN event e ON e.person_id = p.id
INNER JOIN eventtype et ON et.id = e.eventtypeid
) q
GROUP BY
q.Name, q.description
【讨论】:
以上是关于跨三个表的 t-sql 外连接的主要内容,如果未能解决你的问题,请参考以下文章