SQL Server - условное соединение с любой таблицей не равно нулю - PullRequest
2 голосов
/ 21 сентября 2011

Плохо сформулированный заголовок мои извинения.

Я пытаюсь присоединить таблицу к одной из двух других таблиц

MasterTable подтаблица SubTableArchive


Итак, MasterTable содержит поле идентификатора. SubTable и SubTableArchive содержат поле MasterTableId для объединения.

Но данные будут когда-либо существовать только в одной из этих вложенных таблиц. Поэтому я просто хочу присоединиться к любой таблице, в которой есть данные.

Но единственный способ, которым я знаю, - это присоединиться к обоим и использовать isnull's во всех полях, которые я выбрал, и это быстро становится сложным для чтения (и записи). Тем более, что некоторые поля уже обернуты в 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 ]

4 голосов
/ 21 сентября 2011

Другой вариант - использовать UNION, а затем использовать INNER JOINs

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 

С точки зрения обслуживания, если вы сделаете вышеприведенное объединение представлением, вы можете затем применить там, где фильтры и сортировки, к представлению, что должно упростить вопросы.

2 голосов
/ 21 сентября 2011

Использовать вспомогательный или лучший оператор 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
1 голос
/ 21 сентября 2011

Попробуйте это

   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
1 голос
/ 21 сентября 2011

Нет, к сожалению, нет.

0 голосов
/ 22 сентября 2011

Поскольку значение ID из MasterTable будет существовать только в одной таблице (SubTable или SubTableArchive), вы можете использовать этот запрос:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...