我想找到接受所有贷款类型的借款人。

架构:

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一起使用嵌套,在该方法中,我首先找到未全部偿还贷款的借款人,但无法为此创建有效的查询。

最佳答案

一种简单的方法是使用以下事实:

  • ,如果没有联接,则外部联接会为您提供空值
  • coalesce()可以将null转换为空白(始终小于实际值)

  • 因此,没有所有贷款类型的人的最低合并贷款数将为空白:
    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/

    10-11 02:50