簡體   English   中英

從一個表中獲取不滿足其他條件的其他表中不具有相關行的行,而無需子查詢

[英]Getting rows from one table that do not have related rows in other tables meeting specific criteria without subquery

這是SQL提琴

我有一張帶有名稱列表的表。 我想獲取所有在相關表中沒有具有特定狀態('S')或在第3個表中的字段(與第二個表相關)中滿足某個狀態('A'的字段)的名稱的列表')。

我已經能夠使用SQL小提琴及其下面顯示的子查詢來完成此操作,但是如果可能的話,我希望在沒有子查詢的情況下執行此操作。

SELECT * FROM name_table LEFT JOIN 
  (SELECT b.name_id FROM b LEFT JOIN c ON (b.c_id = c.id) WHERE (c.c_status = 'A') OR (b.b_status='S'))
 results ON (name_table.id=results.name_id)
WHERE results.name_id IS NULL;

在我的示例中,我想要“ Ted Andrews”和“ Jack Johnson”行

不包含“ John Doe”,因為表C具有狀態為“ A”的行。不包含“ Bill Smith”,因為表B具有狀態為“ S”。不包含“ Jim Scott”,因為表C具有狀態為“ A”的行'(即使表C中還有另一行的狀態為“ A”)

 SELECT * FROM name_table 
  LEFT JOIN b ON (name_table.id = b.name_id)
 LEFT JOIN c ON (b.c_id = c.id) AND (c_status = 'A');
  WHERE (b.b_status IS NULL) OR ((b.b_status <> 'S') AND (c.id IS NULL));

嘗試錯誤地包含“ Jim Scott”

我會這樣做( sqlfiddle ):

  SELECT nt.first, nt.last
    FROM name_table nt
         LEFT JOIN b ON nt.id  = b.name_id
         LEFT JOIN c ON nt.id  = c.a_id
GROUP BY first, last
  HAVING SUM(IF(b.b_status = 'S',1,0)) = 0
     AND SUM(IF(c.c_status = 'A',1,0)) = 0;

擁有位僅用於計數狀態符號實例,這些實例將人員排除在所需結果集中,並且不需要任何實例。

SELECT name_table.id, min(first) as first, min(last) as last
FROM name_table
   LEFT JOIN b ON name_table.id = b.name_id
   LEFT JOIN c ON b.c_id = c.id
GROUP BY name_table.id
HAVING
        count(case when b.b_status = 'S' then 1 end) = 0
    and count(case when c.c_status = 'A' then 1 end) = 0;

由於您必須查看c中的多行以確定是否有匹配項,因此您會發現自己使用某種聚合。 我個人認為查詢不是那么可怕。

即使您說不應該將Jim Scott包括在內,但在我看來,他的b_status都不是“ S”,c_status也不是“ A”。 這是您要找的東西嗎?

select * from name_table
join b on name_table.id = b.name_id and b.b_status <> 'S'
join c on b.c_id = c.id and c.c_status <> 'A';

這是一種不使用子查詢的方法,盡管我想針對大型數據集檢查其性能:

SELECT a.*
FROM name_table AS a
LEFT JOIN b ON a.id = b.name_id
LEFT JOIN c ON b.c_id = c.id
GROUP BY a.id
HAVING MIN((b.b_status IS NULL OR b.b_status <> 'S') AND (c.c_status IS NULL OR c.c_status <> 'A'));

HAVING子句的每一行求值為0或1,以表明它是否符合您的條件,然后在所有名稱中取最小值,以確保排除Jim Jim Scott-僅包括所有聯接行與您的條件匹配的名稱。

在這種情況下not exists會有所幫助

select
      *
from name_table t
where not exists (select null from B
                  where t.id = b.name_id and b.b_status = 'S')
and not exists (select null from C
                where t.id = c.a_id and c.c_status = 'A')

演示結果

| id | first |     last |
|----|-------|----------|
|  3 |   Ted | Anderson |
|  5 |  Jack |  Johnson |

暫無
暫無

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

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