【问题标题】:How to do a full outer join如何进行完全外部联接
【发布时间】:2019-01-10 09:53:07
【问题描述】:

我使用THEATRES.NUMOFROWS, THEATRES.NUMOFCOLS 设置THEATRES 大小,每个SEAT.SEATNO 都绑定到THEATRES.ID,SHOWTIMES.ID 绑定到THEATRES.ID,TICKET_ITEMS 绑定到SHOWTIMES.ID

我想通过使用 showtime.id 的 where 子句加入表来显示所有值。我知道外部联接将在不匹配时显示 null,但我的查询仅显示一条记录。

SELECT 
    SHOWTIMES.ID AS SHOWTIMESID,
    SHOWTIMES.THEATREID,
    THEATRES.THEATRENAME,
    THEATRES.NUMOFROWS,
    THEATRES.NUMOFCOLS,
    SEAT.SEATNO AS SEATLABEL,
    SEAT.ROWID,
    SEAT.COLUMNID,
    TICKET_ITEMS.SEATNO,
    TICKET_ITEMS.TICKETCODE
FROM
    SHOWTIMES FULL OUTER JOIN TICKET_ITEMS ON SHOWTIMES.ID =TICKET_ITEMS.SHOWTIMESID
     FULL OUTER JOIN THEATRES ON SHOWTIMES.THEATREID = THEATRES.ID
     FULL OUTER JOIN SEAT ON SEAT.SEATNO = TICKET_ITEMS.SEATNO
WHERE
    SHOWTIMES.ID = 1

;

【问题讨论】:

  • 能否添加一些示例数据?

标签: sql sql-server


【解决方案1】:

如果您使用任何类型的OUTER JOIN 并且您引用了WHERE 中的列,您需要处理NULLs。如果不这样做,则将JOIN 转换为隐式INNER JOIN。举个简单的例子:

WITH T1 AS(
    SELECT ID, SomeString
    FROM (VALUES(1,'abc'),(2,'def')) V(ID, SomeString)),
T2 AS(
    SELECT ID, fID, AnotherString
    FROM (VALUES(1,1,'asd'),(2,1,'asdased')) V(ID, fID, AnotherString))
SELECT *
FROM T1
     LEFT JOIN T2 ON T1.ID = T2.ID
WHERE T2.AnotherString = 'asd';

您可能希望在此处获得 2 行,其中 T1.ID 是带有连接行的 1,而 T1.ID 的 1 是 2,但没有连接行。由于WHERE,情况并非如此。这里正确的解决方案是将WHERE移动到ON:

WITH T1 AS(
    SELECT ID, SomeString
    FROM (VALUES(1,'abc'),(2,'def')) V(ID, SomeString)),
T2 AS(
    SELECT ID, fID, AnotherString
    FROM (VALUES(1,1,'asd'),(2,1,'asdased')) V(ID, fID, AnotherString))
SELECT *
FROM T1
     LEFT JOIN T2 ON T1.ID = T2.ID
                 AND T2.AnotherString = 'asd';

有了你所拥有的,你不能这样做,因为你正在使用基表,因此你需要通过将 WHERE 更改为来处理 NULL:

WHERE SHOWTIMES.ID = 1 OR SHOWTIMES.ID IS NULL;

【讨论】:

    【解决方案2】:

    我想你的数据库已经设置了正确的外键关系——所以一个表中的剧院 id 是一个有效的 id。

    如果是这样,您不需要full join。事实上,它很少需要。我怀疑内部连接就足够了(但这就是你得到的结果)。

    如果您希望所有剧院都有合适的节目(如果有的话),请使用 left join 并从剧院开始:

    select st.ID AS SHOWTIMESID, st.THEATREID,
           th.THEATRENAME, th.NUMOFROWS, th.NUMOFCOLS,
           s.SEATNO AS SEATLABEL, s.ROWID, s.COLUMNID,
           ti.SEATNO, ti.TICKETCODE
    from theatres th left join
         showtimes st
         on st.theatreid = th.id and st.id = 1 left join
         ticket_items ti
         on st.ID =ti.showtimesid left join
         seat s
         on s.seatno = ti.seatno
    

    【讨论】:

    • 它不应该是“s.seatno = ti.seatno”,因为“s.seat”代表所有座位,“ti.seatno”只存储购买的票。但我想显示所有这些,但有一个额外的列显示“ti.ticketcode”以表示销售类型
    • @KIRPALSINGH。 . .您应该只用适当的样本数据和期望的结果提出另一个问题。
    猜你喜欢
    • 2011-01-06
    • 2011-07-26
    • 1970-01-01
    • 2021-11-17
    • 2017-10-27
    • 2014-03-10
    相关资源
    最近更新 更多