2012-02-01 52 views
6

該表具有'Sales_Order_ID','Sales_Order_Line_Number'和'Sales_Order_Line_staus'等字段。我想檢索'Sales_Order_ID',其中'Sales_Order_ID'的每個記錄具有相同的'Sales_Order_Line_Status'。如何在銷售訂單的每一行都關閉的情況下獲得銷售訂單?

因此,如果銷售訂單X的每個記錄都具有「關閉」狀態,那麼我想檢索它。如果銷售訂單Y有三個狀態爲「已關閉」的記錄和一個狀態爲「已打開」的記錄,那麼我不想檢索它。

我想:

SELECT DISTINCT s1.so_ID, s1.SO_line_status 
FROM sales_order_table s1 
INNER JOIN sales_order_table s2 
ON s1.so_id = s2.so_id 
    AND s1.so_line_status = s2.so_line_status 
ORDER BY s1.so_id 

要沒有成功。下面似乎給了我想要的東西相反:

SELECT DISTINCT s1.so_ID, s1.SO_line_status 
FROM sales_order_table s1 
INNER JOIN sales_order_table s2 
ON s1.so_id = s2.so_id 
    AND s1.so_line_status <> s2.so_line_status 
ORDER BY s1.so_id 

所以,我想:

SELECT DISTINCT s1.so_ID, s1.SO_line_status 
FROM sales_order_table s1 
INNER JOIN sales_order_table s2 
ON s1.so_id = s2.so_id 
    AND NOT s1.so_line_status <> s2.so_line_status 
ORDER BY s1.so_id 

要沒有成功。

然後我完全noob並改變了連接類型,只是希望它能工作。我在這裏關閉還是完全以錯誤的方式去做?另外,我意識到上面的查詢並不會限制結果爲「關閉」狀態,但我想如果我能得到一個只返回所有相同狀態行的結果,那麼我可以將它們限制爲「關閉」。

對不起,如果這不清楚!如果是這樣,我會盡力澄清。

回答

5
SELECT so_ID 
FROM sales_order_table 
GROUP BY so_ID 
HAVING MAX(SO_line_status) = 'Closed' AND 
     MIN(SO_line_status) = 'Closed' AND 
     COUNT(CASE WHEN SO_line_status IS NULL THEN 1 END) = 0 

你也可以使用EXCEPT如果您的RDBMS支持它

SELECT so_ID 
FROM sales_order_table 
WHERE SO_line_status = 'Closed' 
EXCEPT 
SELECT so_ID 
FROM sales_order_table 
WHERE SO_line_status IS NULL OR SO_line_status <> 'Closed' 
+0

可能的邊緣情況:如果給定'so_ID'的一行或多行具有NULL'SO_line_status',其餘爲'Closed',則'so_ID'將被錯誤地返回,因爲聚合函數忽略NULL。 – 2012-02-01 19:29:27

+0

「HAVING MAX(SO_line_status)= MIN(SO_line_status)''怎麼樣? – 2012-02-01 19:32:15

+0

@MarcusAdams - 因爲OP對封閉狀態特別感興趣。 「我想如果我能得到一個只返回所有相同狀態的線,那麼我可以將它們限制爲」關閉「。」 – 2012-02-01 19:32:55

2

這裏的基本方法是按ID和狀態進行分組。如果該分組的計數等於只有ID的計數,那麼您將知道所有行都具有相同的狀態。

SELECT s1.so_ID, s1.SO_line_status 
    FROM sales_order_table s1 
    GROUP BY s1.so_ID, s1.SO_Line_status 
    HAVING COUNT(*) = (SELECT COUNT(*) 
          FROM sales_order_table s2 
          WHERE s2.so_ID = s1.so_ID) 

爲了縮小範圍,只是 '封閉' 狀態,只需添加一個WHERE子句:

SELECT s1.so_ID, s1.SO_line_status 
    FROM sales_order_table s1 
    WHERE s1.SO_line_status = 'closed' 
    GROUP BY s1.so_ID, s1.SO_Line_status 
    HAVING COUNT(*) = (SELECT COUNT(*) 
          FROM sales_order_table s2 
          WHERE s2.so_ID = s1.so_ID) 
2

Joe's approach應該肯定有效。這裏有幾個備選方案(可能可以或不可以更優化):

反轉問題,篩選出狀態爲Open(或!Closed,取決於您有多少個狀態)的問題:

SELECT T1.Id 
FROM Table as T1 
LEFT JOIN (SELECT Id FROM Table WHERE Status <> 'Closed') as T2 ON 
    T1.Id = T2.Id 
WHERE T2.Id IS NULL 

使用MAX和MIN作爲分組功能:

SELECT Id 
FROM Table 
GROUP BY Id, Status 
HAVING MAX(Status) = 'Closed' 

使用2個派生表:

SELECT C.Id 
FROM (
    SELECT Id FROM Table WHERE Status = 'Closed' 
) as C 
LEFT JOIN (
    SELECT Id FROM Table WHERE Status = 'Open' 
) as O ON 
    C.Id = O.Id 
WHERE O.Id IS NULL 

我懷疑2 LEFT JOIN方法會優化最好的方法,其次是MAX版本,然後是COUNT--但是如果性能對您很重要,您絕對應該進行配置。缺乏性能方面的考慮,我個人發現2個派生表最易讀 - 其他人可能不同意。

1

可以使用所有運營商:

SELECT DISTINCT Sales_Order_ID 
FROM sales_order_table t1 
WHERE 
    'Closed' = ALL (
     SELECT Sales_Order_Line_Staus 
     FROM sales_order_table t2 
     WHERE t1.sales_order_id = t2.sales_order_id 
    ) 

用簡單的英語:選擇那些Sales_Order_ID S表示,所有相關的行具有相同的狀態,以及狀態恰好是「關閉」。


如果你想任何狀態,你可以很容易地做到這一點...

SELECT DISTINCT Sales_Order_ID, Sales_Order_Line_Staus 
FROM sales_order_table t1 
WHERE 
    Sales_Order_Line_Staus = ALL (
     SELECT Sales_Order_Line_Staus 
     FROM sales_order_table t2 
     WHERE t1.sales_order_id = t2.sales_order_id 
    ) 

...甚至這個(如果你在實際Sales_Order_Line_Staus不感興趣):

SELECT Sales_Order_ID 
FROM sales_order_table 
GROUP BY Sales_Order_ID 
HAVING COUNT(DISTINCT Sales_Order_Line_Staus) = 1 
相關問題