Sql server 与表联接,但仅限于特定条件
我需要添加联接,但仅当满足特定条件时 让我举例说明 我有这三张桌子 表ISql server 与表联接,但仅限于特定条件,sql-server,sql-server-2014,Sql Server,Sql Server 2014,我需要添加联接,但仅当满足特定条件时 让我举例说明 我有这三张桌子 表I I_ID Value Ischecked Region ---- ----- --------- ------ 1 A 0 N1 2 B 1 N1 3 C 0 N2 表\u PB PB_ID Region Code -----
I_ID Value Ischecked Region
---- ----- --------- ------
1 A 0 N1
2 B 1 N1
3 C 0 N2
表\u PB
PB_ID Region Code
----- ------ ----
1 N1 A1
2 N1 A2
3 N1 A3
4 N2 C1
表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
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
我是如何得到这个结果的?
我从Table_I
的所有行开始,用Table_D
连接它们,最后用Table_PB
问题是,如果在
表D
中找不到任何行,并且被检查为1
,那么我需要在表PB
上添加一个额外的连接,该连接将添加具有与表I
中相同区域的所有行
我希望我的意思很清楚
所以我现在得到的是这个
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
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的行的差异
可以这样做吗?如何做?尝试用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\u ID
,它来自@Table\u PB
表(对代码进行了注释)。您可以使用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)
简单的解决方案,我并没有想到使用union来实现这一点,但它会起作用。另外,我并不真的需要PB_ID
我只是将它保留在我的示例中,以清楚地表明该连接没有返回任何rowstory,我复制了两次。。。现在已修复抱歉,我正在计算机上运行更新,无法使用我在记事本上编码的SSM