SQL根据多个条件过滤行并获取匹配的记录

时间:2018-10-06 06:23:17

标签: sql-server

您好,我有一个要求,我需要过滤具有多个条件的行,如果匹配中存在单个条目,则排除结果。这是我的样本表

DECLARE @CUSTOMER TABLE
(
    CUSTOMERID INT,
    CUSTOMERNAME NVARCHAR(100)
)

DECLARE @ORDER TABLE
(
    ORDERID INT,
    CUSTOMERID INT,
    ISSPECIALORDER INT,
    SPECIALORDERID INT
)

DECLARE @SPECIALORDERDTL TABLE
(
    SPECIALORDERID INT,
    SPECIALORDERDATAID INT
)

DECLARE @SPECIALORDERDATA TABLE
(
    SPECIALORDERDATAID INT,
    SPECIALORDERMASTERID INT
)

INSERT INTO @CUSTOMER VALUES (100,'CUSTOMER1'),(200,'CUSTOMER2'),(300,'CUSTOMER3'),(400,'CUSTOMER4`enter code here`')

INSERT INTO @ORDER VALUES (1,100,0,1),(2,100,1,1),(3,100,1,2),(4,200,0,1),(5,200,1,1),(6,200,1,4),(7,300,1,5),(8,400,1,6)

INSERT INTO @SPECIALORDERDTL VALUES(1,1),(2,1),(3,2),(4,4)

INSERT INTO @SPECIALORDERDATA VALUES(1,1),(2,1),(3,1),(4,2),(5,2) -- 2 a special order

SELECT  C.CUSTOMERID,C.CUSTOMERNAME
FROM    @ORDER O
INNER JOIN @CUSTOMER C ON C.CUSTOMERID=O.CUSTOMERID

INNER JOIN @SPECIALORDERDTL SO ON SO.SPECIALORDERID = O.SPECIALORDERID
INNER JOIN @SPECIALORDERDATA SOD ON SO.SPECIALORDERDATAID = SOD.SPECIALORDERDATAID
WHERE SOD.SPECIALORDERID <> 2 AND O.ISSPECIALORDER =0
    GROUP BY C.CUSTOMERID,C.CUSTOMERNAME
    ORDER BY C.CUSTOMERNAME

当我在@SPECIALORDERDT L中有一个SPECIALORDERMASTERID为2的条目时,我需要将它们视为特殊条目并排除它们。因此,我的查询应该只返回100的客户。

3 个答案:

答案 0 :(得分:2)

从您的描述或SQL中不清楚确切需要什么。据我了解:

DECLARE @CUSTOMER TABLE
(
    CUSTOMERID INT,
    CUSTOMERNAME NVARCHAR(100)
)

DECLARE @ORDER TABLE
(
    ORDERID INT,
    CUSTOMERID INT,
    ISSPECIALORDER INT,
    SPECIALORDERID INT
)

DECLARE @SPECIALORDERDTL TABLE
(
    SPECIALORDERID INT,
    SPECIALORDERDATAID INT
)

DECLARE @SPECIALORDERDATA TABLE
(
    SPECIALORDERDATAID INT,
    SPECIALORDERMASTERID INT
)

INSERT INTO @CUSTOMER VALUES 
(100,'CUSTOMER1'),
(200,'CUSTOMER2'),
(300,'CUSTOMER3'),
(400,'CUSTOMER4')

INSERT INTO @ORDER VALUES 
(1,100,0,1),
(2,100,1,1),
(3,100,1,2),
(4,200,0,1),
(5,200,1,1),
(6,200,1,4),
(7,300,1,5),
(8,400,1,6)

INSERT INTO @SPECIALORDERDTL VALUES(1,1),(2,1),(3,2),(4,4)

INSERT INTO @SPECIALORDERDATA VALUES(1,1),(2,1),(3,1),(4,2),(5,2) -- 2 a special order

SELECT  C.CUSTOMERID,C.CUSTOMERNAME
from @Customer c
where exists (select * from @ORDER o where o.CustomerId = c.CustomerId)
and not exists (
select * 
from @ORDER O
LEFT JOIN @SPECIALORDERDTL SO ON SO.SPECIALORDERID = O.SPECIALORDERID
LEFT JOIN @SPECIALORDERDATA SOD ON SO.SPECIALORDERDATAID = SOD.SPECIALORDERDATAID
WHERE (SO.SPECIALORDERID IS NULL 
or SOD.SPECIALORDERMASTERID = 2 --AND O.ISSPECIALORDER =0
) AND O.CustomerId = c.CustomerId
);
GO
CUSTOMERID | CUSTOMERNAME
---------: | :-----------
       100 | CUSTOMER1   

db <>提琴here

答案 1 :(得分:1)

假设我理解了这个问题,我认为Have子句中的条件聚合可能是获得所需结果的最简单方法:

ClassB

having子句会过滤掉每个与至少一个与其相关的订单的specialordermasterid为2的客户。

答案 2 :(得分:0)

从您的描述看来,并不是每个客户都会在SPECIALORDERDTL或SPECIALORDERDTA中有一个条目,因此您不想内部连接到这些表。

您需要的是一个“不存在”的相关子查询,以检查客户在这些表中没有匹配的行。

因此,您可以删除SPECIAL *表的内部联接,并添加以下内容:-

 where not exists (select null from SPECIALORDERDTL SO where
 SO.SPECIALORDERID = O.SPECIALORDERID and SO.SPECIALORDERMASTERID = 2)

根据您的描述,我不确定“ SOD.SPECIALORDERID <> 2 AND O.ISSPECIALORDER = 0”在哪里适合,因此,如果您无法使用子查询来解析,请提供输出的更多详细信息。

在您澄清之后,请尝试执行以下操作:-

SELECT  distinct C.CUSTOMERID,C.CUSTOMERNAME
FROM    @ORDER O
INNER JOIN @CUSTOMER C ON C.CUSTOMERID=O.CUSTOMERID
where not exists 
(select null from @SPECIALORDERDTL SO 
INNER JOIN @SPECIALORDERDATA SOD ON SO.SPECIALORDERDATAID = SOD.SPECIALORDERDATAID 
where SO.SPECIALORDERID = O.SPECIALORDERID and 
SOD.SPECIALORDERMASTERID = 2
)
order by C.CUSTOMERNAME