跨三个表的t-sql外连接

时间:2010-11-22 10:54:39

标签: tsql outer-join

我有三张桌子:

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行,而不管事件表的内容如何。

我可以在两个表之间使用外连接(例如,所有事件类型的持续时间),但不能使用第二个外连接。

谢谢!

3 个答案:

答案 0 :(得分:2)

您必须在混音中添加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        

答案 1 :(得分:1)

您可以交叉加入person和eventtype,然后将结果加入事件表:

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

交叉连接是指对于左表中的每一行,它连接到右表中的每一行。

答案 2 :(得分:1)

如果您想为personeventtype的每个组合添加一行,则会产生CROSS JOIN。要获取我们需要加入event的持续时间,但这需要是OUTER加入,因为可能并不总是有一行。您对“总计”的使用表明,对于eventperson的给定组合,可能会有多个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)

输出:

{{1}}