这是一个家庭作业问题。我想找到所有贷款的客户。该表如下。
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
这里的答案是汤姆。
现在,出于学习目的,要求是我不允许计算贷款总数并将借款人的贷款数量与之比较,如果可以使用的话,这完全有效。
所以我想到的是看到所有借款人的贷款都存在于贷款表中。我试图通过首先获得没有所有贷款的客户来做双重否定,但这不起作用。有关如何进行此操作的任何提示?考虑到我不允许这样做,这是最好的方法吗?
我觉得它看起来并不像看起来那么复杂,但我自己也无法弄明白。
答案 0 :(得分:2)
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);
无需计算:
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;
它将返回没有所有贷款的客户。 然后,您只需将其从所有客户中删除。
使用EXCEPT
(SQL Server):
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 |
+------+