查找在他们居住的同一城市的所有分支机构拥有帐户的所有客户

问题描述 投票:1回答:2

我有以下表格。

account(account_number, branch_name, balance)
branch(branch_name, branch_city, assets)
customer(customer_name, customer_street, customer_city)
loan(loan_number, branch_name, amount)
depositor(customer_name, account_number)
borrower(customer_name, loan_number)

Crude visual representation of this schema

我想编写一个SQL查询,选择所有在他们居住的同一城市的所有分支机构拥有帐户的客户。

我知道如何为特定城市做到这一点,例如'Perryridge':

SELECT DISTINCT S.customer_name
FROM depositor S
WHERE NOT exists(
    (SELECT branch_name
     FROM branch
     WHERE branch_city = 'Perryridge')
    EXCEPT
    (SELECT branch_name
     FROM depositor D, account A
     WHERE D.account_number = A.account_number AND
           D.customer_name = A.customer_name))

基本上我选择Perryridge的所有分支,除了客户的分支。如果结果为空,那么客户就拥有了所有结果。

我试图概括这个查询以检查branch_city = customer_city是否可以让它选择所有在他们所居住的城市的所有分支中拥有帐户的客户,但它显然不起作用,因为它取出与其他分支相关的分支顾客。

任何人都可以帮我解决这个问题吗?

sql postgresql
2个回答
0
投票

请注意,以下解决方案对不同表之间的关系做了一些假设,因为它们没有明确定义以及许多属性的唯一性。话虽如此,这是它的工作原理:

您首先找到每个客户(存款人)以及他所拥有的分支机构和城市的名称。(我们暂时根据问题中与OP相关的SQL忽略贷款账户,但他们很容易如果需要,使用UNION操作进行调整)。我们进一步将此最小化以删除冗余条目,以适应使用GROUP BY在同一分支机构拥有多个帐户的一个客户。

使用branch_name和city从所有已注册分支到上述结果的LEFT JOIN将导致城市中每个分支的行连接。 (您希望使用这两个属性进行连接,因为例如名为Downtown的分支可能位于多个城市中)。

其余的是对名称匹配的所有行中没有branch_name空值的客户进行过滤。正如嵌入在having子句中的case语句所示,这是通过将行分为两类来完成的:

  • 如果匹配的branch_names中没有找到空值,那么总和为0的那些。
  • 那些增加了失踪分支数量的那些

选择前者应该会引导您找到您想要的结果。

select x.customer_name
from branch bb
left outer join
( -- Names of customers who have accounts in branches in their own city
    select d.customer_name, 
           b.branch_name, 
           b.branch_city
    from depositor d 
    inner join account a on d.account_number = a.account_number
    inner join branch b on b.branch_name = a.branch_name
    inner join customer c on c.customer_name = d.customer_name 
    where c.customer_city = b.branch_city
    group by d.customer_name, b.branch_name, b.branch_city
) x
on ( 
        x.branch_name = bb.branch_name and 
        x.branch_city = bb.branch_city
   )
group by x.customer_name
having sum(
            case 
                when x.branch_name is null then 1 
                else 0 
            end
          )=0;

可能有一些我没有看到的东西,从所需的输出略微偏斜,但这是一般的方法,如果它不能按原样工作,可以很容易地调整到要求。


0
投票

我不确定我是否理解将客户分拆为借款人或存款人的原因。理想情况下,您应该为客户存储帐号。您还可以按帐号存储贷款编号。我们假设不同城市的分支机构不能有相同的名称?

无论如何,您需要加入分支机构的帐户以获取分支机构的所有帐户,并加入存款人和客户以获取客户的帐号(可能还需要在那里加入贷款)。然后你可以找到平等的帐户和城市

例如

CREATE TEMP TABLE branch_accounts AS 
SELECT branch_name, branch_city, account_number
FROM branch NATURAL JOIN account;

CREATE TEMP TABLE deposit_customers AS 
SELECT account_number, customer_name, customer_city 
FROM customer NATURAL JOIN depositor;

SELECT customer_name, branch_name 
FROM JOIN branch_accounts B, deposit_customers D ON B.branch_city = D.customer_city AND B.account_number = D.account_number;

你需要与分支机构,贷款和借款人类似的东西

© www.soinside.com 2019 - 2024. All rights reserved.