SQL Server - 条件连接到任何表不为null

时间:2011-09-21 12:46:30

标签: sql sql-server-2005 tsql join

严厉的标题我的道歉。

我正在尝试将表连接到另外两个表之一

MasterTable 子表 SubTableArchive


因此,MasterTable包含一个ID字段。 SubTable和SubTableArchive包含连接的MasterTableId字段。

但是,数据只会存在于其中一个SubTable中。所以我只想加入其中包含数据的表。

但我知道这样做的唯一方法是加入两者并在我选择的所有字段上使用isnull,并且很快就会变得难以阅读(和写入)。 特别是因为有些字段已经包含在ISNULL的

SELECT M.Id, ISNULL(S.Field1, SA.field1), ISNULL(S.field2, SA.Field2),
SUM(CASE WHEN (ISNULL(S.Finished,SA.Finished)=1 AND ISNULL( ISNULL(S.ItemCode,SA.ItemCode),'')='') THEN 1 WHEN (ISNULL(S.Finished,SA.Finished)=0 AND ISNULL( ISNULL(S.AltItemCode,SA.AltItemCode),'')='') THEN 1 ELSE 0 END) AS SummaryField
FROM MAsterTable M
LEFT OUTER JOIN SubTable S ON S.MasterTableId = M.Id
LEFT OUTER JOIN SubTableArchive SA ON S.MasterTableId = M.Id
GROUP BY M.Id, ISNULL(S.Field1, SA.field1), ISNULL(S.field2, SA.Field2)

这样才有用,但它并不漂亮。 这是一个样本,但真正的查询更长,更复杂。

我希望SQL可能内置了某种条件连接功能。 要做的事情我要做的事情,让查询更友好一点。

5 个答案:

答案 0 :(得分:4)

另一个选择是使用UNION然后使用INNER JOIN

SELECT M.x, S.x
FROM MAsterTable M INNER JOIN SubTable S ON S.MasterTableId = M.Id 
UNION
SELECT M.x, STA.x
FROM MAsterTable M INNER JOIN SubTableArchive STA ON STA.MasterTableId = M.Id 

从维护的角度来看,如果您将上述联合作为视图,则可以应用过滤器和排序到视图的位置,这样可以简化问题。

答案 1 :(得分:2)

使用sub-select或更好的WITH语句(代码未测试):

WITH SubTable_WithArchive 
AS (SELECT  Field1, Field2, Finished, ItemCode, AltItemCode, MasterTableID
    FROM    SubTable
    UNION ALL
    SELECT  Field1, Field2, Finished, ItemCode, AltItemCode, MasterTableID
    FROM    SubTableArchive
)
SELECT  M.Id, 
        S.Field1,
        S.Field2,
        SUM(CASE
                WHEN s.Finished = 1 AND ISNULL(s.ItemCode, '') == '' THEN 1
                WHEN s.Finished = 0 AND ISNULL(s.AltItemCode, '') == '' THEN 1
                ELSE 0
            END)
            AS SummaryField

FROM            MasterTable M
LEFT OUTER JOIN SubTable_WithArchive S
            ON  S.MasterTableId = M.Id
GROUP BY        M.Id, S.Field1, s.field2

答案 2 :(得分:1)

不,不幸的是,没有。

答案 3 :(得分:1)

试试这个

   SELECT M.Id, S.Field1,S.field2, 
    SUM(CASE WHEN S.Finished=1 AND ISNULL( S.ItemCode,'')='') 
        THEN 1 
        WHEN S.Finished=0 AND ISNULL( S.AltItemCode,'')='') 
        THEN 1 ELSE 0 END) AS SummaryField
    FROM MAsterTable M
    JOIN (
         SELECT id,field1,field2,ItemCode,AltItemCode,finished
         FROM subTable 
         UNION
         SELECT id,field1,field2,ItemCode,AltItemCode,finished
         FROM subTableArchive 
    ) S  ON S.id = M.Id

    GROUP BY M.Id, S.Field1,S.field2

答案 4 :(得分:0)

由于MasterTable中的ID值仅存在于一个表(SubTableSubTableArchive)中,因此您可以使用此查询:

SELECT MasterTableId Id, Field1, Field2,
SUM(CASE 
WHEN Finished=1 AND ItemCode IS NULL THEN 1 --OR ISNULL(ItemCode,'') = ''
WHEN Finished=0 AND AltItemCode IS NULL THEN 1 --OR ISNULL(AltItemCode,'') = ''
ELSE 0 
END) AS SummaryField
FROM SubTable
GROUP BY 1, 2, 3

UNION ALL

SELECT MasterTableId Id, Field1, Field2,
SUM(CASE 
WHEN Finished=1 AND ItemCode IS NULL THEN 1 --OR ISNULL(ItemCode,'') = ''
WHEN Finished=0 AND AltItemCode IS NULL THEN 1 --OR ISNULL(AltItemCode,'') = ''
ELSE 0 
END) AS SummaryField
FROM SubTableArchive
GROUP BY 1, 2, 3