如何获得销售订单的每一行都已关闭的销售订单?

时间:2012-02-01 19:03:43

标签: sql

该表在其他字段中包含“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并改变了连接类型,只是希望它能工作。我是在这里关闭还是以错误的方式完成它?

另外,我意识到上面的查询不会将结果限制为“已关闭”状态,但我想如果我能得到一个只返回所有相同状态行的结果,那么我可以将它们限制为“已关闭”。

对不起,如果不清楚的话!如果是这样,我会尽力澄清。

4 个答案:

答案 0 :(得分: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

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

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' 

答案 1 :(得分: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)

将其缩小至“关闭”状态。 status,只需添加一个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 :(得分: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个派生表最具可读性 - 其他人可能不同意。

答案 3 :(得分:1)

您可以使用ALL运算符:

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,并且该状态恰好为“已关闭”。


如果您想要任何状态,您可以轻松地执行此操作...

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