使用简单的Join / Subquery初学SQL问题

时间:2014-02-12 10:46:57

标签: sql sql-server

我知道这是一个非常基本的查询,但我无法找到满足我需求的解决方案,所以这里有...

我有一个客户表INT_AUX_LISTING,一个文件夹表,其中包含INT_AUX_DIRECTORY和一个连接表INT_AUX_DIR_LIST。

我需要返回文件夹40017中所有客户的列表,而不是文件夹2中的任何其他文件夹。

到目前为止,我已经提出了

SELECT * 
  FROM INT_AUX_LISTING l 
       LEFT JOIN INT_AUX_DIR_LIST dl 
                 ON l.LISTING_ID=dl.LISTING_ID
 WHERE dl.CONTAIN_DIR_ID=40017
   AND dl.CONTAIN_DIR_ID <> 2

然而,(显然)这是不正确的,并返回太多的值。我想我需要引入一个子查询但是当我尝试时出现问题。

对问题的入门级性质表示歉意,但这只是我第三天使用SQL!

3 个答案:

答案 0 :(得分:0)

您的WHERE子句是问题所在;它会返回除id不为2的行之外的所有行,包括id为40017的行(因为它不等于2)。我想你应该重新审视它。

答案 1 :(得分:0)

如果您在INT_AUX_LISTING上使用LEFT JOIN [1],即使他们没有相应的文件夹,您也会获得所有客户。在您的情况下,最好使用INNER JOIN [2]

在where子句中,您是第一个语句选择文件夹40017中的客户(dl.CONTAIN_DIR_ID = 40017),因此您的第二个语句(dl.CONTAIN_DIR_ID&lt;&gt; 2)将始终为真(40017)永远不会等于2)。所以基本上你选择文件夹40017中的所有客户。

你的子查询概念是正确的。这是获得理想结果的一种方法:

SELECT * 
FROM INT_AUX_LISTING l 
    INNER JOIN INT_AUX_DIR_LIST dl1 
        ON l.LISTING_ID = dl1.LISTING_ID
WHERE dl1.CONTAIN_DIR_ID = 40017
    AND l.LISTING_ID NOT IN (
        SELECT dl2.LISTING_ID FROM INT_AUX_DIR_LIST dl2 WHERE dl2.CONTAIN_DIR_ID = 2
    )

答案 2 :(得分:0)

首先,澄清左连接和哪里。如果你有一个对表有左连接的查询(根据你的例子,其中“dl”是连接的右侧),然后将“dl”别名添加到where子句,那实质上是转换它到INNER JOIN(除非您使用OR dl.listing_ID IS NULL显式测试)。

现在,回到主要目标。如果没有表结构,并且对列意图不完全清楚,则表示“listing_id”列是您在int_aux_listing表中找到的客户端。 “contains_dir_id”是int_aux_dir_list中的目录(可能是其中之一)。

也就是说,你想要一个40017而不是2的所有人的列表。为此,你可以做一个左连接,但是使用int_aux_listing表两次,但是使用不同的别名。获得客户端列表后,可以将其加入客户端表。由于您是新手,请一步一步地取样。

只需获得40017以内的客户

select
      dl.listing_id
   from
      int_aux_dir_list dl
   where
      dl.contain_dir_id = 40017

现在,排除那些在目录2中找到的

select
      dl.listing_id
   from
      int_aux_dir_list dl
         left join int_aux_dir_list dl2
            on dl.listing_id = dl2.listing_id
           AND dl2.contain_dir_id = 2
   where
          dl.contain_dir_id = 40017
      AND dl2.listing_id IS NULL

通过第二次对目录列表进行左连接(通过别名“dl2”),但专门针对其目录id = 2(通过AND dl2.contain_dir_id = 2),您将从dl获取所有客户端在目录40017内并在第二个实例(“dl2”)中查找相同的客户机ID。

这是踢球者。注意where子句声明“AND dl2.listing_id IS NULL”。

这基本上是说WHEN在查看DL2实例时,我只想要没有匹配相应列表ID的记录。

现在,将其打包以获取您需要的客户端信息。在这种情况下,从目录列表中获取所有列(以防其他重要列),并从“l”表中获取所有列。

select
      dl.*,
      l.*
   from
      int_aux_dir_list dl
         left join int_aux_dir_list dl2
            on dl.listing_id = dl2.listing_id
           AND dl2.contain_dir_id = 2
         join INT_AUX_LISTING l
            on dl.listing_id = l.listing_id
   where
          dl.contain_dir_id = 40017
      AND dl2.listing_id IS NULL

希望这能为你解决问题。