复杂SQL使用基于集合的操作排除逻辑

时间:2013-10-01 13:41:44

标签: sql sql-server sql-server-2008

我更喜欢使用set逻辑而不是用光标或其他东西迭代表,但如果需要它就可以完成。

我基本上准备了一个存储过程中的视图,该视图将在别处用于BI。现在,存储过程只是一个select语句,从具有大量连接和其他随机逻辑的各种表中提取。

以下是关于表格外观的示例。首先,将返回的表,第二个用户想要进行的排除。 Example

我想查看excludes表中的每条记录,然后将其作为过滤器应用于第一个表,这样就可以消除项匹配的所有行。 (它将会变得更加复杂,因为他们可以选择消除整个LocationCode,然后级联所有WarehouseCode及其下面的所有内容。它基本上是一个层次结构。但我想要了解一般的想法)。

我不知道怎么用NOT EXISTS来做,因为我必须一行一行。我不确定我是否必须使用游标或以其他方式迭代。我想知道SQL中是否还有其他工具我不知道。

任何有关如何根据其他表值有效消除行的建议都将不胜感激,谢谢。

3 个答案:

答案 0 :(得分:1)

如果你想从Table1获得整行,除了Table2中有类似的行,你可以这样做:

select * -- Column list here
from Table1 as t
where
    not exists (
        select t.LocationCode, t.WarehouseCode, t.WarehouseName, t.StorageAddress
        intersect
        select t2.LocationCode, t2.WarehouseCode, t2.WarehouseName, t2.StorageAddress
        from Table2 as t2
    )

或更方便

select * -- Column list here
from Table1 as t
where
    not exists (
        select *
        from Table2 as t2
        where
            t2.LocationCode = t.LocationCode and
            t2.WarehouseCode = t.WarehouseCode and
            t2.WarehouseName = t.WarehouseName and
            t2.StorageAddress = t.StorageAddress
    )

答案 1 :(得分:0)

查看EXCEPT子句,其与UNION

的工作方式类似
select col1, col2, col3 from yourtable
EXCEPT
select col1, col2, col3 from exceptions

答案 2 :(得分:0)

这里要解决两件事。在第一种情况下,您已解释Exclude表具有与实际表中相同的列数。我在这里假设这个表中的一些列将是 “NULL able”,有些可能不是。所以在排除期间你也需要照顾它。由于性能原因,我认为“Left Join”是一个很好的候选者,并且只有在需要时才可以对所选列执行MATCHING。在你的情况下,现在似乎所有列都需要匹配,但如果在表上添加了像列这样的标识/日期时间/时间戳,请考虑将来。 看下面的代码。如果这个表中的数据量很大,那么NON-Clustered和/或Filter Index将帮助你提高性能,但是如果你看到视图查询很慢,那就是在后期阶段。

对于您提到的第二部分,稍后您可能决定完全排除位置代码,并且存在分层依赖关系。 我会说保持这个独立,直到你有确切的要求。

    DECLARE @AllData TABLE
    (
        ID      INT         NOT NULL PRIMARY KEY
        ,FName  sysname     NOT NULL
        ,LName  sysname     NOT NULL
        ,MName  sysname     NULL
    )

    DECLARE @ExcludeData TABLE
    (
        ID      INT         NOT NULL PRIMARY KEY
        ,FName  sysname     NOT NULL
        ,LName  sysname     NOT NULL
        ,MName  sysname     NULL
    )

    INSERT INTO @AllData( ID, FName, LName, MName )
                SELECT 1,'Fname1','Lname1','MName1'
    UNION ALL   SELECT 2,'Fname2','Lname2',NULL
    UNION ALL   SELECT 3,'Fname3','Lname3','Mname3'
    UNION ALL   SELECT 4,'Fname4','Lname4',NULL

    INSERT INTO @ExcludeData( ID, FName, LName, MName )
                SELECT 1,'Fname1','Lname1','MName1'
    UNION ALL   SELECT 2,'Fname2','Lname2',NULL

    SELECT a.ID,a.FName,a.LName,a.MName
    FROM @AllData a
    LEFT JOIN @ExcludeData b
    ON 
        ((a.ID=b.ID) OR (a.id IS NULL AND b.id IS NULL))
        AND
        ((a.FName=b.FName) OR (a.FName IS NULL AND b.FName IS NULL))
        AND
        ((a.LName=b.LName) OR (a.LName IS NULL AND b.LName IS NULL))
        AND
        ((a.MName=b.MName) OR (a.MName IS NULL AND b.MName IS NULL))
    WHERE 
        (b.ID IS NULL AND b.FName IS NULL AND b.LName IS NULL AND b.MName IS NULL)
相关问题