TSQL通过排除条件连接4个表

时间:2017-11-24 14:58:58

标签: sql sql-server tsql join

我目前正在处理SQL Server 2014上的查询。我尝试在表[table_ad_attribute]中使用排除条件对4个表进行连接。[FK_attribute] = 42。

表始终是连接的,PK_ID = FK_Tablename:

SELECT [A].PK_ID, [B].Surname, [B].Firstname
FROM [dbo].[client] [A]

INNER JOIN [dbo].[contact] [B]
   ON [B].FK_Client = [A].PK_ID
  AND [A].Type = 22

// i assume this join is wrong
INNER JOIN [dbo].[ad] [C]
   ON [C].FK_Client = [A].PK_ID

INNER JOIN [dbo].[table_ad_attribute] [D]
   ON [D].FK_ad = [C].PK_ID 
  AND [D].FK_attribute = 42

问题是,当我执行查询时,我得到了一个无限循环。执行需要很长时间,并且会多次显示很多条目。我认为这是因为第二次内部联接。也许我应该使用另一种连接类型?

一些示例数据:

dbo.client

PK_ID | Type
-------------
 1    |  22
 2    |  33

dbo.contact

PK_ID | FK_Client | Surname | Lastname
---------------------------------------
 12   |  1        | Doe     | John

dbo.ad

PK_ID | FK_Client
-----------------
 54   |  1

dbo.table_ad_attribute

FK_ad | FK_attribute
---------------------
 54   |   42

所需的输出:

PK_ID | Surname | Firstname
---------------------------
  1   | Doe     | John

您知道如何解决这个问题吗?也许在这种情况下加入哪个?

感谢您的帮助!

2 个答案:

答案 0 :(得分:0)

您正在加入[A] - > [B]获取结果列。

您还加入[A] - > [C] - > [D]来获取你的过滤器。

我认为发生的事情是你的过滤器正在返回每个[A] .PK_ID值的多个实例,这样你就可以为每个[A]返回[A] [B]行的数量.PK_ID值。

假设我是对的,我会做这样的事情,

SELECT [A].PK_ID, [B].Surname, [B].Firstname
  FROM [dbo].[client] [A]

 INNER JOIN [dbo].[contact] [B]
    ON [B].FK_Client = [A].PK_ID
   AND [A].Type = 22

 WHERE [A].PK_ID IN (SELECT DISTINCT [C].FK_Client
                       FROM [dbo].[ad] [C]

                      INNER JOIN [dbo].[table_ad_attribute] [D]
                         ON [D].FK_ad = [C].PK_ID 
                        AND [D].FK_attribute = 42)

你的[C] - > [D] join标识您感兴趣的[A] .PK_ID值,因此我将其放入子查询中,然后我在WHERE子句中使用[A] - > [B]加入。

答案 1 :(得分:0)

为什么要加入所有这些表?您似乎想要通过联系人选择客户端并以某种方式限制它。因此,加入客户和联系人,并将您的标准放在WHERE子句中。这将为您提供所有类型22的客户,其中包含42个广告及其联系人:

select cl.pk_id, co.surname, co.firstname
from dbo.client cl
join dbo.contact co on co.fk_client = cl.pk_id
where cl.type = 22
and cl.pk_id in
(
  select fk_client
  from dbo.ad
  where pk_id in (select fk_ad from dbo.table_ad_attribute where fk_attribute = 42)
);