我想找到接受所有贷款类型的借款人。
架构:
loan (number (PKEY), type, min_rating)
borrower (cust (PKEY), no (PKEY))
样本表:
number | type | min_rating
------------------------------
L1 | student | 500
L2 | car | 550
L3 | house | 500
L4 | car | 700
L5 | car | 900
cust | no
-----------
Jim | L2
Tom | L1
Tom | L2
Tom | L3
Tom | L4
Tom | L5
Bob | L3
答案是“汤姆”。
我可以简单地计算贷款总数,然后将借款人的贷款数量与贷款总数进行比较,但是出于这项功课和学习的目的,我不允许这样做(这是一项家庭作业)。
我想使用双重否定,即首先找到未全部偿还贷款的借款人,再找到不在该组中的借款人。我想与
NOT EXISTS
一起使用嵌套,在该方法中,我首先找到未全部偿还贷款的借款人,但无法为此创建有效的查询。 最佳答案
一种简单的方法是使用以下事实:
因此,没有所有贷款类型的人的最低合并贷款数将为空白:
select cust
from borrower b
left join loan l on l.number = b.no
group by cust
having min(coalesce(l.number, '')) > ''
分组方式巧妙地回避了不止一次选择人员的问题(以及经常需要的丑陋的子查询),并基于相当合理的假设,即贷款号码永远不会为空。即使有可能,您仍然可以找到一种使该模式起作用的方法(例如,将min_rating合并为负数,等等)。
可以使用
NOT IN
表达式重新编写上面的查询(可能更可读):select distinct cust
from borrower
where cust not in (
select cust
from borrower b
left join loan l on l.number = b.no
where l.number is null
)
通过使用错过的联接返回所有null的事实,内部查询的where子句仅保留错过的联接。
您需要使用
DISTINCT
来阻止借款人出现两次。您的架构存在问题-借方与负载之间存在多对多关系,但是您的架构处理得很差。
borrower
每个人应该有一行,并且还有另一个关联表来记录借款人借贷的事实:create table borrower (
id int,
name varchar(20)
-- other columns about the person
);
create table borrrower_loan (
borrower_id int, -- FK to borrower
load_number char(2) -- FK to loan
);
这意味着您将不需要
distinct
运算符(由您自己找出原因),而且可以处理现实生活中的情况,例如两个借款人的名字相同。关于sql - 借款人使用NOT EXISTS取得所有贷款,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/33176522/