获得所有贷款的客户

时间:2015-10-15 22:35:20

标签: mysql sql

这是一个家庭作业问题。我想找到所有贷款的客户。该表如下。

Schema:
loan (number (PKEY), type, min_rating)
borrower (cust (PKEY), no (PKEY))

Sample tables:
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

这里的答案是汤姆。

现在,出于学习目的,要求是我允许计算贷款总数并将借款人的贷款数量与之比较,如果可以使用的话,这完全有效。

所以我想到的是看到所有借款人的贷款都存在于贷款表中。我试图通过首先获得没有所有贷款的客户来做双重否定,但这不起作用。有关如何进行此操作的任何提示?考虑到我不允许这样做,这是最好的方法吗?

我觉得它看起来并不像看起来那么复杂,但我自己也无法弄明白。

3 个答案:

答案 0 :(得分:2)

LiveDemo

CREATE TABLE #loan(
   number VARCHAR(7) NOT NULL 
  ,type   VARCHAR(8) NOT NULL
);
INSERT INTO #loan(number,type) VALUES ('L1','student');
INSERT INTO #loan(number,type) VALUES ('L2','car');
INSERT INTO #loan(number,type) VALUES ('L3','house');
INSERT INTO #loan(number,type) VALUES ('L4','car');
INSERT INTO #loan(number,type) VALUES ('L5','car');


CREATE TABLE #borrower(
   cust  VARCHAR(7) NOT NULL 
  ,no VARCHAR(8) NOT NULL);

INSERT INTO #borrower VALUES ('Jim','L2'), ('Tom','L1'), ('Tom','L2'), ('Tom','L3'),
                             ('Tom','L4'), ('Tom','L5'), ('Bob','L3');

SELECT cust
FROM (
  SELECT b.cust, COUNT(DISTINCT type) AS c
  FROM #loan l
  JOIN #borrower b
    ON l.number = b.no
    GROUP BY b.cust) AS s
WHERE s.c = (SELECT COUNT(DISTINCT type) FROM #loan);

编辑:

LiveDemo2

无需计算:

SELECT main.cust
FROM (SELECT DISTINCT cust FROM #borrower) AS main
LEFT JOIN (
  SELECT DISTINCT sub2.cust
  FROM (
    SELECT DISTINCT cust, type
    FROM #borrower b
    JOIN #loan l
      ON b.no = l.number) as sub
    RIGHT JOIN (
    SELECT b.cust, s.type
    FROM #borrower b
    CROSS JOIN (SELECT DISTINCT type FROM #loan) AS s) AS sub2
      ON sub.cust = sub2.cust AND sub.type = sub2.type
    WHERE sub.cust IS NULL
) AS sub3
  ON main.cust = sub3.cust
WHERE sub3.cust IS NULL;

工作原理:

SELECT DISTINCT sub2.cust
  FROM (
SELECT DISTINCT cust, type
FROM #borrower b
JOIN #loan l
  ON b.no = l.number) as sub
RIGHT JOIN (
    SELECT b.cust, s.type
    FROM #borrower b
    CROSS JOIN (SELECT DISTINCT type FROM #loan) AS s) AS sub2
  ON sub.cust = sub2.cust AND sub.type = sub2.type
WHERE sub.cust IS NULL;

它将返回没有所有贷款的客户。 然后,您只需将其从所有客户中删除。

EDIT2:

使用EXCEPT(SQL Server):

LiveDemo3

SELECT main.cust
FROM #borrower AS main
EXCEPT 
(
  SELECT cust
  FROM (
   SELECT b.cust, s.type
   FROM #borrower b
   CROSS JOIN (SELECT DISTINCT type FROM #loan) AS s
   EXCEPT
   SELECT cust, type
   FROM #borrower b
   JOIN #loan l
     ON b.no = l.number ) AS sub
)

答案 1 :(得分:0)

由于您有不同类型的贷款,只需加入一次以检查每种类型:

SELECT bStudent.cust
FROM borrower bStudent
JOIN loan hasStudent ON bStudent.no = hasStudent.no AND hasStudent.type = 'student'
JOIN borrower bCar ON bStudent.cust = bCar.cust
JOIN loan hasCar ON bCar.no = hasCar.no AND hasCar.type = 'car'
JOIN borrower bHouse ON bStudent.cust = bHouse.cust
JOIN loan hasHouse ON bCar.no = hasHouse.no AND hasHouse.type = 'house';

第一次加入将使所有借款人获得学生贷款,第二次加入将与拥有汽车贷款的借款人相匹配,第三次加入将与拥有房屋贷款的借款人相匹配。

<强>更新

好的,我们假设我们不知道有多少类型的贷款......回到你的双重否定想法!第一步,将每个借款人映射到他们的贷款类型:

SELECT cust, type
FROM borrower b
JOIN loan l
USING (no);

...然后我们会找到所有不同类型的贷款......

SELECT DISTINCT type FROM loan

......找到错过某种贷款的人......

SELECT DISTINCT cust
FROM (SELECT cust, type
    FROM borrower b
    JOIN loan l
    USING (no)) custLoanTypes
LEFT OUTER JOIN (SELECT DISTINCT type FROM loan) loanTypes
USING (type)
WHERE loanTypes.type IS NULL;

...然后从不同的借款人名单中减去那些。

SELECT DISTINCT cust FROM borrower b
LEFT OUTER JOIN (
    SELECT DISTINCT cust
    FROM (SELECT cust, type
        FROM borrower b
        JOIN loan l
        USING (no)) custLoanTypes
    LEFT OUTER JOIN (SELECT DISTINCT type FROM loan) loanTypes
    USING (type)
    WHERE loanTypes.type IS NULL) custsMissingALoan
USING (cust)
WHERE custsMissingALoan.cust IS NULL;

多么有趣的谜题。

答案 2 :(得分:0)

如果您考虑以下架构......

CREATE TABLE loan(
   loan_id CHAR(2) NOT NULL 
  ,type   VARCHAR(12) NOT NULL
);
INSERT INTO loan VALUES 
('L1','student'),
('L2','car'),
('L3','house'),
('L4','car'),
('L5','car');


CREATE TABLE borrower(
   name  VARCHAR(7) NOT NULL 
  ,loan_id CHAR(2) NOT NULL
);
INSERT INTO borrower VALUES 
('Jim','L2'),
('Tom','L1'), 
('Tom','L2'), 
('Tom','L3'), 
('Tom','L4'), 
('Tom','L5'), 
('Bob','L3');

...那么您似乎想要返回未出现在此列表中的所有用户的姓名......

SELECT DISTINCT b.name 
           FROM borrower b 
           JOIN loan l 
           LEFT 
           JOIN borrower bx 
             ON bx.name = b.name 
            AND bx.loan_id = l.loan_id 
          WHERE bx.name IS NULL;

+------+
| name |
+------+
| Jim  |
| Bob  |
+------+