присоединиться к столу, но только при определенных условиях - PullRequest
0 голосов
/ 19 февраля 2019

Мне нужно добавить соединение, но только при соблюдении определенного условия.

Позвольте мне объяснить на примере.

У меня есть эти 3 таблицы

Table_I

I_ID    Value   Ischecked   Region  
----    -----   ---------   ------  
1       A       0           N1  
2       B       1           N1  
3       C       0           N2  

Table_PB

PB_ID   Region  Code    
-----   ------  ----    
1       N1      A1  
2       N1      A2  
3       N1      A3  
4       N2      C1  

Table_D

D_ID    I_ID    PB_ID   
----    ----    -----   
1       1       1   
2       1       2   
3       3       1   
4       3       4   

Мой требуемый результат - это

I_ID    Value   IsChecked   Region  PB_ID   Code    
----    -----   ---------   ------  -----   ----    
1       A       0           N1      1       A1  
1       A       0           N1      2       A2  
2       B       1           N1      null    A1  
2       B       1           N1      null    A2  
2       B       1           N1      null    A3  
3       C       0           N2      1       A1  
3       C       0           N2      4       C1  

Как мне получить этот результат?

Ну, я начинаю со всех строк с Table_I и соединяю их с Table_D и, наконец, с Table_PB
Подвох в том, что когда в Table_D и IsChecked is 1 не найдено ни одной строки, тогда янужно дополнительное соединение на Table_PB, которое добавит все строки с таким же Region, как в Table_I

Надеюсь, понятно, о чем я.

Такто, что я получил сейчас, это

declare @Table_I table (I_ID int, Value varchar(10), Ischecked bit, Region varchar(2))
insert into @Table_I values (1, 'A', 0, 'N1'), (2, 'B', 1, 'N1'), (3, 'C', 0, 'N2')

declare @Table_PB table (PB_ID int, Region varchar(2), Code varchar(2))
insert into @Table_PB values (1, 'N1', 'A1'), (2, 'N1', 'A2'), (3, 'N1', 'A3'), (4, 'N2', 'C1')

declare @Table_D table (D_ID int, I_ID int, PB_ID int)
insert into @Table_D values (1, 1, 1), (2, 1, 2), (3, 3, 1), (4, 3, 4)

select i.I_ID, i.Value, i.IsChecked, i.Region, d.PB_ID, pb.Code
from   @Table_I i
  left outer join @Table_D d on i.I_ID = d.I_ID
  left outer join @Table_PB pb on d.PB_ID = pb.PB_ID 

Это дает этот результат

I_ID    Value   IsChecked   Region  PB_ID   Code    
----    -----   ---------   ------  -----   ----    
1       A       0           N1      1       A1  
1       A       0           N1      2       A2  
2       B       1           N1      null    null    
3       C       0           N2      1       A1  
3       C       0           N2      4       C1  

Когда вы сравните это с моим желаемым результатом, вы увидите разницу для строки с I_ID =2

Можно ли это сделать и как?

Ответы [ 2 ]

0 голосов
/ 19 февраля 2019

Вы можете использовать CTE

declare @Table_I table (I_ID int, Value varchar(10), Ischecked bit, Region varchar(2))
insert into @Table_I values (1, 'A', 0, 'N1'), (2, 'B', 1, 'N1'), (3, 'C', 0, 'N2')

declare @Table_PB table (PB_ID int, Region varchar(2), Code varchar(2))
insert into @Table_PB values (1, 'N1', 'A1'), (2, 'N1', 'A2'), (3, 'N1', 'A3'), (4, 'N2', 'C1')

declare @Table_D table (D_ID int, I_ID int, PB_ID int)
insert into @Table_D values (1, 1, 1), (2, 1, 2), (3, 3, 1), (4, 3, 4)

;
WITH cte AS (
    SELECT i.I_ID, count(D.PB_ID) as CountD
    FROM @Table_I i
    LEFT JOIN @Table_D D ON i.I_ID = d.I_ID 
    GROUP BY i.I_ID
)
SELECT 
    i.I_ID, i.Value, i.IsChecked, i.Region, d.PB_ID, pb.Code
FROM CTE c
  join @Table_I i on i.I_ID = c.i_id
  left join @Table_D d on i.I_ID = d.I_ID
  left join @Table_PB pb on (d.PB_ID = pb.PB_ID) OR (c.CountD = 0 AND i.isChecked = 1 AND i.Region = pb.Region)
0 голосов
/ 19 февраля 2019

Попробуйте разделить логику между двумя наборами с помощью UNION ALL:

-- Records from I that exists on D
SELECT
    I.I_ID,
    I.Value,
    I.Ischecked,
    I.Region,
    D.PB_ID,
    P.Code
FROM
    @Table_I AS I
    INNER JOIN @Table_D AS D ON I.I_ID = D.I_ID
    INNER JOIN @Table_PB AS P ON D.PB_ID = P.PB_ID

UNION ALL

-- Records from I that don't exist on D and are checked
SELECT
    I.I_ID,
    I.Value,
    I.Ischecked,
    I.Region,
    PB_ID = NULL, --P.PB_ID,
    P.Code
FROM
    @Table_I AS I
    INNER JOIN @Table_PB AS P ON I.Region = P.Region
WHERE
    I.Ischecked = 1 AND
    NOT EXISTS (SELECT 'no record on D' FROM @Table_D AS D WHERE D.I_ID = I.I_ID)

ORDER BY
    1

Результаты:

I_ID    Value   Ischecked   Region  PB_ID   Code
1       A       0           N1      1       A1
1       A       0           N1      2       A2
2       B       1           N1      NULL    A1
2       B       1           N1      NULL    A2
2       B       1           N1      NULL    A3
3       C       0           N2      4       C1
3       C       0           N2      1       A1

Я заставляю NULL на втором наборе, потому что он соответствуетВаш желаемый результат, но есть PB_ID, который вы можете отобразить здесь, взятый из таблицы @Table_PB (это комментарий к коду).

...