簡體   English   中英

左外部聯接與外部聯接的一部分具有相同的表

[英]Left Outer join with same table as part of the outer join

我想知道如何通過編寫外部聯接查詢來獲得所需的輸出(如下所述),其中我正在外部聯接的表是語句中其他聯接條件的一部分

給定以下數據結構,其中-表A是包含一些任意對象的主表-表A被A引用,其中A.TYPE_ID = B.ID-表C定義表A中對象之間的關系,其中C.SOURCE_ID引用A.ID和C.TARGET_ID引用A.ID

這是定義架構的方式,我對此無能為力(這是舊系統)

TABLE_A                 
---------------------------
| ID  | TYPE_ID | Name    |
|-------------------------|
| 1   | 1       | Name 1  |
| 2   | 2       | Name 2  |
| 3   | 1       | Name 3  |
| 4   | 1       | Name 4  |
| 5   | 3       | Name 5  |
|-------------------------|

TABLE_B
----------------------
| ID  | TYPE_NAME    |
|--------------------|
| 1   | Type 1       |
| 2   | Type 2       |
| 3   | Type 3       |
| 4   | Type 4       |
|--------------------|

TABLE_C
-------------------------------
| PK  | SOURCE_ID | TARGET_ID |
|-----------------------------|
| 11  | 2         | 1         |
| 12  | 2         | 3         |
| 13  | 5         | 1         |
| 13  | 5         | 4         |
-------------------------------

我想得到的是“類型1”的表A中的所有對象,以及它們所關聯的對象的名稱(否則為null),類型2,即外部聯接,以獲取類型1的所有對象不管他們是否有關聯,但是如果他們有關聯,那么我需要對象的名稱。 請注意,類型1的對象將始終位於關系中的TARGET中。

上面示例的輸出為

-------------------------------
| Target Name | Source Name   |
|-----------------------------|
| Name 1      | Name 2        |
| Name 3      | Name 2        |
| Name 4      | (NULL)        |
|-----------------------------|

我原來的聯接查詢(無法使外部聯接起作用),這是普通聯接,不顯示沒有關聯的對象。

select atrgt.NAME, asrc.NAME
from TABLE_A atrgt
JOIN TABLE_B trgttype on atrgt.TYPE_ID = trgttype.ID
         and trgttype.TYPE_NAME = 'Type 1'
JOIN TABLE_C assoc    on atrgt.ID = assoc.TARGET_ID
JOIN TABLE_A asrc     on asrc.ID = assoc.SOURCE_ID
JOIN TABLE_B srctype  on asrc.TYPE_ID = srctype.ID
         and srctype.TYPE_NAME = 'Type 2'

基本上,在這些情況下,我認為最好的方法是將查詢細分為兩個普通聯接,然后在這些結果集之間進行外部聯接。 如果您將SQL視為過程代碼,您可能會認為它看起來效率低下,但是查詢優化器不一定會獨立運行兩個子聯接。

您沒有說您正在使用什么RDBMS。 在Oracle中,我可能會這樣寫:

with
src_type_2 as (
  select c.target_id, a.name
    from table_c c
    join table_a on a.id = c.source_id
    join table_b on b.id = a.type_id
    where b.type_name = 'Type 2'
),
all_type_1 as (
  select a.id, a.name
  from table_a a
  join table_b on b.id = a.type_id
  where b.type_name = 'Type 1'
)
select tgt.name, src.name
  from all_type_1 tgt
  left join src_type_2 src on src.target_id = tgt.id

嘗試

select atrgt.NAME, baseview.NAME
from TABLE_A atrgt
JOIN TABLE_B trgttype on atrgt.TYPE_ID = trgttype.ID
         and trgttype.TYPE_NAME = 'Type 1'
JOIN TABLE_C assoc    on atrgt.ID = assoc.TARGET_ID
LEFT JOIN ( 
  TABLE_A asrc     on asrc.ID = assoc.SOURCE_ID
  JOIN TABLE_B srctype  on asrc.TYPE_ID = srctype.ID
         and srctype.TYPE_NAME = 'Type 2'
  ) as baseview

我認為這應該工作:

SELECT
    TGT.NAME, SRC_TYPE.TYPE_NAME
FROM TABLE_A TGT
JOIN TABLE_B TGT_TYPE ON TGT.TYPE_ID = TGT_TYPE.ID
LEFT JOIN TABLE_C REL ON TGT.ID = REL.TARGET_ID
LEFT JOIN TABLE_A SRC ON REL.SOURCE_ID = SRC.ID
LEFT JOIN TABLE_B SRC_TYPE ON SRC_TYPE.ID = SRC.TYPE_ID
WHERE TGT_TYPE.TYPE_NAME = 'Type 1' AND COALESCE(SRC_TYPE.TYPE_NAME, 'Type 2') = 'Type 2'

如果使用的是Oracle,則可以用NVL(SRC_TYPE.TYPE_NAME, 'Type 2')替換COALESCE

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM