2014-01-18 44 views
3

如實例行,給出的方案:返回有各種出現在一個表給定屬性

account(id, type, cname) 

我想與出現在帳戶的各個type返回cname的客戶的account

下面的查詢將做到:

SELECT cname, type 
FROM account AS cust_account 
WHERE NOT EXISTS ( 
    SELECT type 
    FROM account 
    EXCEPT 
    SELECT type 
    FROM account 
    WHERE account.cname = cust_account.cname 
); 

不過,我無法理解其背後的邏輯。特別是,我沒有看到EXCEPT聲明發生了什麼。有人可以澄清這一點嗎?謝謝。

+0

我想我理解其中的邏輯,但我沒有找到在該查詢的意義。這就像一個遞歸查詢,但是「NOT EXISTS」對我來說毫無意義。你說查詢的工作原理..你能舉一個你的數據的例子以及該數據查詢的結果嗎? – carexcer

回答

5

由於WHERE NOT EXIST子句處理每個記錄,它會爲該記錄中的客戶運行以下步驟。如果它從步驟#3看到空列表,它將在查詢結果中包含該客戶(NOT EXISTS)。

  1. 列出所有可能的賬戶類型。
  2. 列出該客戶擁有的所有帳戶類型。
  3. 在步驟#2中減去列表#步驟#1中的列表。這將創建該客戶沒有的任何賬戶類型的列表。對於擁有所有帳戶的客戶而言,這將是空的。

需要明確的是,由於WHERE NOT EXIST子句包含相關子查詢,因此步驟1-3(由子查詢執行)針對帳戶表中的每一行運行一次。例如,如果帳戶表包含100,000,則子查詢將運行100,000次。

+0

我瞭解子查詢,但我不明白,完整的查詢可能會返回任何行,因爲子查詢讀取'cust_account',並有一個遞歸,我不理解如何完成查詢可能會返回一些東西。我認爲總是返回0行。 – carexcer

+2

@Carexcer:嘗試解壓你的子查詢並且一次爲一個客戶運行它來查看它的功能。對於擁有所有類型的客戶,它不會返回任何內容。對於只有一些賬戶的客戶,它將返回客戶沒有的賬戶。我也添加到我的答案。 – poke

+0

@poke:非常感謝你,這是一個很明確的解釋,它讓我能夠看到如何比較'account.cname'中的_every_行和'cust_account.cname'中的_just one_行'需要別名表! 出於好奇,有沒有更好的方法來達到同樣的效果?它作爲一個查詢實際上是否有意義,或者它只是一個巧妙的方式來顯示'NOT EXISTS'如何工作? – laurids

1

基本上,原始查詢將只顯示那些客戶不具有不在(EXCEPT)的類型的完整列表(SELECT type FROM account)< =>別[帳戶](WHERE NOT EXISTS)類型(SELECT type FROM account WHERE account.cname = cust_account.cname)」沒有(WHERE NOT EXISTS)所有類型的帳戶。

一個更加簡單的寫這個查詢的方法是:

SELECT x.cname 
FROM dbo.Account x 
GROUP BY x.cname 
HAVING COUNT(DISTINCT x.type) = (SELECT COUNT(DISTINCT y.type) FROM dbo.Account y) 

或本

SELECT a.cname, a.type 
FROM dbo.Account a 
WHERE a.cname IN 
(
    SELECT x.cname 
    FROM dbo.Account x 
    GROUP BY x.cname 
    HAVING COUNT(DISTINCT x.type) = (SELECT COUNT(DISTINCT y.type) FROM dbo.Account y) 
) 
+0

對不起,我以前沒有看到您的答案,這也幫助我很多!謝謝。 – laurids

相關問題