Join

如果所有子值都在查詢中,則選擇父值

  • January 27, 2018

我有三個類似於下面範例的表

T1                                   T3
------------------------             --------------------------
T1ID       X         ...             T3ID          Z        ...
------------------------             --------------------------
  1       aaa                          1          abc
  2       bbb                          2          def
  3       ccc                          3          ghi
  4       ddd                          4          jkl
                                       5          mno


T2
----------------------------------------
T2ID      T1ID      T3ID      Y     ...
----------------------------------------
  1         1         1      eee
  2         2         1      fff
  3         3         1      ggg
  4         2         2      hhh
  5         2         3      iii
  6         3         3      jjj
  7         1         4      kkk
  8         2         4      lll
  9         3         5      mmm
 10         4         5      nnn      

我想要的是所有 3 個表的內部連接,但如果 T2 中引用 T1 中選定值的所有值都是先前建立的查詢的一部分,我只想選擇 T3 中的值。因此,例如,如果先前建立的查詢 (Q1) 選擇了 T1ID 的 1 和 2,那麼我希望此查詢選擇 T3ID 的 1 和 4。典型的連接將選擇 T3ID 的 1、2、3 和 4,但我不希望 T3ID 的 2和 3 被選中,因為 T3ID 2 和 3 的值不包括 T2 中的 T1ID 1。T3ID 1 也可以在 T2 中包含其他 T1ID 以供選擇。(我沒有能力改變數據庫設計,所以請不要對改變它發表評論。目前這個數據庫在 MS Access 中)

假設您的初始查詢結果的值為 1 和 2,您將返回兩個值,您現在可以將其插入到HAVING子句中。

您可以使用它來搜尋 T3ID 在有兩個匹配項時出現的次數。

這段程式碼是用 T-SQL 編寫的,但我相信您可以很容易地將其轉換為 Access,因為無論如何它都是出於展示目的。

-- This returns the T3IDs that match the conditions
SELECT T3ID
FROM T2
WHERE T3ID IN (1, 2)
GROUP BY T3ID
HAVING COUNT(T3ID) = 2 -- to match on the number of values

這將返回兩個值:1 和 4。現在您可以將該結果插入現有的 INNER JOIN 查詢中,該查詢返回所有內容,只需添加 WHERE 子句。

例如:

SELECT * FROM T2
WHERE T3ID IN (
   SELECT T3ID
   FROM T2
   WHERE T3ID IN (1, 2)
   GROUP BY T3ID
   HAVING COUNT(T3ID) = 2
)

您需要用表格格式的清晰輸出重新解釋。

樣本數據,

declare @T1  table(T1ID int,X varchar(20))
insert into @T1 VALUES         
(1,'aaa') ,(2,'bbb')                     
,(3,'ccc') ,(4,'ddd')                     


declare @T3 table(T3ID int,Z varchar(20))
 insert into @T3 VALUES  
(1,'abc'),(2,'def')
 ,(3,'ghi'),(4,'jkl'),(5,'mno')

declare @T2 table(T2ID int,T1ID int,T3ID int,Y varchar(10))
insert into @T2 VALUES
( 1,1,1,'eee')
,( 2,2,1,'fff')
,( 3,3,1,'ggg')
,( 4,2,2,'hhh')
,( 5,2,3,'iii')
,( 6,3,3,'jjj')
,( 7,1,4,'kkk')
,( 8,2,4,'lll')
,( 9,3,5,'mmm')
,(10,4,5,'nnn')  

sql伺服器版本

;With CTE as
(
select * from @T1
where T1ID in(1,2)
)
,CTE1 AS(
select t2.T3ID from @T2 t2
inner join cte c
on t2.T1ID=c.t1id
group by t2.T3ID
having count(*)=(select count(*) from cte)
)
select t3.* 
from @T3 t3
inner join cte1 c1 on t3.T3ID=c1.t3id

我使用 CTE 因為我不知道您之前建立的查詢是什麼。如果我知道,則可能會相應地重寫查詢

MS Access 版本我已經使用相同的範例數據在 MS Access 中創建並執行此查詢。

select t3.* from T3 t3

inner join
(
select t2.t3id from T2 t2 
inner join
(
select * from T1
where T1ID in(1,2)
)t4
on t2.T1ID=t4.t1id
group by t2.T3ID
having count(*)=(select count(*) from T1
where T1ID in(1,2))
)t5
on t3.t3id=t5.t3id

以前建立查詢的地方是

select * from T1
   where T1ID in(1,2)

你必須擔心這個查詢。

引用自:https://dba.stackexchange.com/questions/152191