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

时间:2018-01-02 01:54:56

标签: sql postgresql

我有以下表格。

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是否可以选择所有在他们所居住的城市的所有分支中拥有帐户的客户,但很明显不起作用,因为它取出与其他客户相关联的分支机构。

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

2 个答案:

答案 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;

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

答案 1 :(得分: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;

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