提问人:evanburen 提问时间:10/24/2023 最后编辑:evanburen 更新时间:10/24/2023 访问量:37
排除具有部分匹配条件的记录
Exclude Records With Partial Matching Conditions
问:
我有两个表,Person 和 Loan_Dtl,我希望我的结果只显示所有贷款都符合以下条件的人。如果此人有多种贷款,其中一些符合这些条件,而另一些则不符合这些条件,那么该人不应出现在结果中。
- 输入l.loan_type_cd ('D0','D1','D2','D3','D5','D6','D7','D8','D9')
- 和 (l.opb_amt + l.oib_amt) > 0
- AND l.loan_status_cd = 'RP'
- 和 l.repymt_plan_type_cd IN ('C1', 'C2', 'C3', 'I3', 'I4', 'I5', 'IB', 'IC', 'IL', 'IS', 'J5', 'P1', 'PA', 'RA')
- l.loan_holder_cd输入 ('578', '580', '500', '507', '512')
我下面的代码用于显示混合了一些匹配贷款的人。在示例数据中,D2'、'RP'、'I5'、250、50 是结果中唯一包含的贷款,但此人 (2544541) 根本不应包含在结果中,因为他有其他不匹配的贷款。我只需要所有贷款都匹配的人。2544542的人应该出现在结果中,因为他只有匹配的贷款。
SELECT
COUNT(DISTINCT p.person_id) AS Borrower_Count
,SUM(l.opb_amt + l.oib_amt) as balance
FROM person p INNER JOIN
loan_dtl l on p.person_id = l.brwr_person_id
WHERE
NOT EXISTS
(SELECT 1
FROM loan_dtl l2
WHERE l.loan_id = l2.loan_id
AND l2.loan_type_cd NOT IN
('D0','D1','D2','D3','D5','D6','D7','D8','D9')
)
AND NOT EXISTS
(SELECT 1
FROM loan_dtl l2
WHERE l.loan_id = l2.loan_id
AND (l.opb_amt + l.oib_amt) = 0
)
AND NOT EXISTS
(SELECT 1
FROM loan_dtl l2
WHERE l.loan_id = l2.loan_id
AND l.loan_status_cd NOT IN ('RP')
)
AND NOT EXISTS
(SELECT 1
FROM loan_dtl l2
WHERE l.loan_id = l2.loan_id
AND l.repymt_plan_type_cd NOT IN ('C1', 'C2', 'C3', 'I3', 'I4', 'I5',
'IB', 'IC', 'IL', 'IS', 'J5', 'P1', 'PA', 'RA')
)
AND NOT EXISTS
(SELECT 1
FROM loan_dtl l2
WHERE l.loan_id = l2.loan_id
AND l.loan_holder_cd NOT IN ('578', '580', '500', '507', '512')
)
表格和数据:
CREATE TABLE [dbo].[Loan_dtl](
[loan_id] [int] NULL,
[brwr_person_id] [int] NULL,
[loan_holder_cd] [int] NULL,
[loan_type_cd] [varchar](50) NULL,
[loan_status_cd] [varchar](50) NULL,
[REPYMT_PLAN_TYPE_CD] [varchar](50) NULL,
[OPB_AMT] [int] NULL,
[OIB_AMT] [int] NULL
) ON [PRIMARY]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Person](
[person_id] [int] NULL
) ON [PRIMARY]
GO
INSERT [dbo].[Loan_dtl] ([loan_id], [brwr_person_id],
[loan_holder_cd], [loan_type_cd], [loan_status_cd],
[REPYMT_PLAN_TYPE_CD], [OPB_AMT], [OIB_AMT]) VALUES (124677158,
2544541, 755, N'CL', NULL, NULL, 25824, 3261)
GO
INSERT [dbo].[Loan_dtl] ([loan_id], [brwr_person_id],
[loan_holder_cd], [loan_type_cd], [loan_status_cd],
[REPYMT_PLAN_TYPE_CD], [OPB_AMT], [OIB_AMT]) VALUES (124919090,
2544541, 755, N'CL', NULL, NULL, 37708, 4761)
GO
INSERT [dbo].[Loan_dtl] ([loan_id], [brwr_person_id],
[loan_holder_cd], [loan_type_cd], [loan_status_cd],
[REPYMT_PLAN_TYPE_CD], [OPB_AMT], [OIB_AMT]) VALUES (102070274,
2544541, 507, N'D2', N'RP', N'I5', 250, 50)
GO
INSERT [dbo].[Loan_dtl] ([loan_id], [brwr_person_id],
[loan_holder_cd], [loan_type_cd], [loan_status_cd],
[REPYMT_PLAN_TYPE_CD], [OPB_AMT], [OIB_AMT]) VALUES (102070266,
2544541, 507, N'SF', NULL, N'IB', 737, 189)
GO
INSERT [dbo].[Loan_dtl] ([loan_id], [brwr_person_id],
[loan_holder_cd], [loan_type_cd], [loan_status_cd],
[REPYMT_PLAN_TYPE_CD], [OPB_AMT], [OIB_AMT]) VALUES (102070269,
2544541, 507, N'D1', NULL, N'IB', 0, 0)
GO
INSERT [dbo].[Loan_dtl] ([loan_id], [brwr_person_id],
[loan_holder_cd], [loan_type_cd], [loan_status_cd],
[REPYMT_PLAN_TYPE_CD], [OPB_AMT], [OIB_AMT]) VALUES (102070280,
2544542, 507, N'D2', N'RP', N'I5', 950, 5)
GO
INSERT [dbo].[Person] ([person_id]) VALUES (2544541)
GO
INSERT [dbo].[Person] ([person_id]) VALUES (2544542)
GO
答:
1赞
Aaron Bertrand
10/24/2023
#1
我认为你的逻辑的主要问题是你的子句与 .因此,来自任何特定人的所有贷款,但未被排除在外的贷款仍将归还。您需要将该相关性更改为。我认为可以简化为一个简单的子句:NOT EXISTS
loan_id
NOT EXISTS
brwr_person_id
NOT EXISTS
WHERE NOT EXISTS
(
SELECT 1 FROM loan_dtl l2
WHERE l.brwr_person_id = l2.brwr_person_id
AND
(
l2.loan_type_cd NOT IN
('D0','D1','D2','D3','D5','D6','D7','D8','D9'))
OR (l.opb_amt + l.oib_amt) = 0
OR l.loan_status_cd NOT IN ('RP')
OR l.repymt_plan_type_cd NOT IN
('C1', 'C2', 'C3', 'I3', 'I4', 'I5', 'IB',
'IC', 'IL', 'IS', 'J5', 'P1', 'PA', 'RA')
OR l.loan_holder_cd NOT IN
('578', '580', '500', '507', '512')
)
);
尽管以下变体对优化器更友好一些(消除了一些昂贵的 SORT 运算符):
SELECT
COUNT(p.person_id) AS Borrower_Count,
SUM(cap.balance) AS balance
FROM dbo.person p CROSS APPLY
(
SELECT SUM(l.opb_amt + l.oib_amt) as balance
FROM dbo.loan_dtl l
WHERE p.person_id = l.brwr_person_id
) AS cap
WHERE NOT EXISTS
(
SELECT 1 FROM dbo.loan_dtl l2
WHERE p.person_id = l2.brwr_person_id
AND
(
l2.loan_type_cd NOT IN
('D0','D1','D2','D3','D5','D6','D7','D8','D9')
OR (l2.opb_amt + l2.oib_amt) = 0
OR l2.loan_status_cd NOT IN ('RP')
OR l2.repymt_plan_type_cd NOT IN
('C1', 'C2', 'C3', 'I3', 'I4', 'I5', 'IB',
'IC', 'IL', 'IS', 'J5', 'P1', 'PA', 'RA')
OR l2.loan_holder_cd NOT IN
('578', '580', '500', '507', '512')
)
);
评论
0赞
evanburen
10/24/2023
太棒了。非常感谢。
0赞
Zorkolot
10/24/2023
#2
您可以筛选主查询以识别所需记录,然后检查person_id是否存在与 DeMorgan 定律相反的条件。
SELECT COUNT(DISTINCT p.person_id) AS Borrower_Count
,SUM(l.opb_amt + l.oib_amt) as balance
FROM [dbo].[Person] p
INNER JOIN Loan_dtl l ON p.person_id = l.brwr_person_id
WHERE l.loan_type_cd IN ('D0','D1','D2','D3','D5','D6','D7','D8','D9')
AND (l.opb_amt + l.oib_amt) > 0
AND l.loan_status_cd = 'RP'
AND l.repymt_plan_type_cd IN ('C1', 'C2', 'C3', 'I3', 'I4', 'I5', 'IB', 'IC', 'IL', 'IS', 'J5', 'P1', 'PA', 'RA')
AND l.loan_holder_cd IN ('578', '580', '500', '507', '512')
AND p.person_id NOT IN (
--DeMorgan's Law, to take the opposite logic
SELECT brwr_person_id
FROM Loan_dtl
WHERE loan_type_cd NOT IN ('D0','D1','D2','D3','D5','D6','D7','D8','D9')
OR (opb_amt + oib_amt) <= 0
OR loan_status_cd <> 'RP'
OR repymt_plan_type_cd NOT IN ('C1', 'C2', 'C3', 'I3', 'I4', 'I5', 'IB', 'IC', 'IL', 'IS', 'J5', 'P1', 'PA', 'RA')
OR loan_holder_cd NOT IN ('578', '580', '500', '507', '512')
)
评论