Sql server 如何排除SELECT中的相同行

Sql server 如何排除SELECT中的相同行,sql-server,Sql Server,我有一个脚本,它创建一个表并存储销售订单信息。它背后的场景是,一旦将商品添加到销售订单中,它的状态为'A'表示添加。后来不知何故,客户希望删除该项目,因此我们添加了一个具有相同详细信息的新行,但状态与'D'的意思是删除。 现在,我只想获取活动的销售订单项目,这些项目不应包括从订单中添加的项目。 这是我的剧本 CREATE TABLE [dbo].[SALE_DETAIL]( [ORDER_NUMBER] [varchar](50) NULL, [ITEM_NAME] [varch

我有一个脚本,它创建一个表并存储销售订单信息。它背后的场景是,一旦将商品添加到销售订单中,它的
状态为
'A'
表示
添加
。后来不知何故,客户希望删除该项目,因此我们添加了一个具有相同详细信息的新行,但
状态
'D'
的意思是
删除
。 现在,我只想获取活动的销售订单项目,这些项目不应包括从订单中添加的项目。 这是我的剧本

CREATE TABLE [dbo].[SALE_DETAIL](
    [ORDER_NUMBER] [varchar](50) NULL,
    [ITEM_NAME] [varchar](250) NULL,
    [QUANTITY] [int] NULL,
    [PRICE] [numeric](18, 0) NULL,
    [Status] [varchar](50) NULL
) ON [PRIMARY]

GO
SET ANSI_PADDING OFF
GO
INSERT [dbo].[SALE_DETAIL] ([ORDER_NUMBER], [ITEM_NAME], [QUANTITY], [PRICE], [Status]) VALUES (N'SO-100-ORD-19', N'Double Bed', 5, CAST(70000 AS Numeric(18, 0)), N'A')
GO
INSERT [dbo].[SALE_DETAIL] ([ORDER_NUMBER], [ITEM_NAME], [QUANTITY], [PRICE], [Status]) VALUES (N'SO-100-ORD-19', N'Sofa', 5, CAST(10000 AS Numeric(18, 0)), N'A')
GO
INSERT [dbo].[SALE_DETAIL] ([ORDER_NUMBER], [ITEM_NAME], [QUANTITY], [PRICE], [Status]) VALUES (N'SO-100-ORD-19', N'Dining Table', 1, CAST(50000 AS Numeric(18, 0)), N'A')
GO
INSERT [dbo].[SALE_DETAIL] ([ORDER_NUMBER], [ITEM_NAME], [QUANTITY], [PRICE], [Status]) VALUES (N'SO-100-ORD-19', N'Sofa', 5, CAST(10000 AS Numeric(18, 0)), N'D')   
GO
我正在寻找的预期输出应该是这样的,因为项目
'Sofa'
已从订单中取消

ORDER_NUMBER    ITEM_NAME       QTY PRICE
SO-100-ORD-19   Dining Table    1   50000
SO-100-ORD-19   Double Bed      5   70000
查询:

SELECT ORDER_NUMBER, ITEM_NAME, QUANTITY, PRICE FROM [dbo].[SALE_DETAIL]
WHERE Status <> 'D'
GROUP BY ORDER_NUMBER, ITEM_NAME, QUANTITY, PRICE
从[dbo]中选择订单号、项目名称、数量、价格。[销售详情]
状态“D”在哪里
按订单号、项目名称、数量、价格分组

我会使用
不存在

SELECT SD.ORDER_NUMBER,
       SD.ITEM_NAME,
       SD.QUANTITY,
       SD.PRICE
FROM dbo.[SALE_DETAIL] SD
WHERE NOT EXISTS (SELECT 1
                  FROM dbo.[SALE_DETAIL] e
                  WHERE e.ORDER_NUMBER = SD.ORDER_NUMBER
                    AND e.ITEM_NAME = SD.ITEM_NAME
                    AND e.[Status] = 'D');
换句话说:选择不存在匹配“D”记录的所有“A”记录

在SQL中:

SELECT ORDER_NUMBER, ITEM_NAME, QUANTITY, PRICE
FROM [dbo].[SALE_DETAIL] X
WHERE Status = 'A'
AND NOT EXISTS (
  SELECT 1
  FROM [dbo].[SALE_DETAIL] Y
  WHERE Y.Status       = 'D'
  AND   Y.ORDER_NUMBER = X.ORDER_NUMBER
  AND   Y.ITEM_NAME    = X.ITEM_NAME
)

从逻辑上讲,基于集合的答案是使用:


这会产生你要求的结果。但是,请注意,无论出于何种原因,这在实践中通常表现不佳,在这种情况下,类似的操作可能是首选的。

您可以尝试使用
not in
操作符获得预期结果,如下所示

SELECT DISTINCT A.ORDER_NUMBER, A.ITEM_NAME,A.QUANTITY, A.PRICE, A.Status
FROM SALE_DETAIL A
    where A.ITEM_NAME not in (select s.ITEM_NAME from SALE_DETAIL s
    where s.[Status] = 'D')
输出如下所示

ORDER_NUMBER    ITEM_NAME   QUANTITY    PRICE   Status
------------------------------------------------------
SO-100-ORD-19   Dining Table    1       50000   A       
SO-100-ORD-19   Double Bed      5       70000   A        

您可以找到现场演示

到目前为止您都尝试了什么?您已经问了足够多的问题,知道您也应该发布您的尝试。这似乎是一个笨拙的数据设计-如果有人插入了一个
D
记录,而该记录在所有细节上都与现有
a
记录不匹配,会发生什么?(全部或仅基于价格)请参阅我的更新答案。
ORDER_NUMBER    ITEM_NAME   QUANTITY    PRICE   Status
------------------------------------------------------
SO-100-ORD-19   Dining Table    1       50000   A       
SO-100-ORD-19   Double Bed      5       70000   A