0

创建一个视图,其中包含在 Perryridge 分行拥有贷款和帐户的所有客户的姓名。

对此有什么想法吗?我很困惑是否使用存在或


这些表是:

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

1 回答 1

1

您可以在查询中使用 anEXISTSIN谓词。要么会工作。

(“视图”本质上是一个查询。因此,首先,问题实际上是关于制定返回指定结果集的查询。一旦有了查询,只需将其包装在 CREATE VIEW 语句中即可。我会注意这里我们通常不会在 MySQL 数据库中使用视图。这是因为 MySQL 优化器的工作方式,它总是将视图查询具体化为派生表,这与其他 DBMS 中处理视图查询的方式不同。)

假设您有单独的表customeraccount和/或loan,您可能需要EXISTS谓词、IN谓词或连接操作,或它们的某种组合。

例如,此查询(如下)使用谓词来测试表和表EXISTS中是否存在匹配行,并返回在 Perryridge 分行具有至少一个关联帐户和至少一个关联贷款的行。accountloancustomer

SELECT c.name
  FROM customer c
 WHERE EXISTS ( SELECT 1 
                  FROM account a
                 WHERE a.customer_id = c.id 
                   AND a.branch = 'Perryridge' 
              )
   AND EXISTS ( SELECT 1 
                  FROM loan l
                 WHERE l.customer_id = c.id
              )

此查询(如下)返回一个等效的结果集,但使用IN谓词在 account 和 loan 表中查找匹配的行:

SELECT c.name
  FROM customer c
 WHERE c.id IN ( SELECT a.customer_id
                   FROM account a
                  WHERE a.branch = 'Perryridge'
               )
   AND c.id IN ( SELECT l.customer_id
                  FROM loan l
               )

这个查询(如下)利用 JOIN 操作来查找匹配的行。JOIN 的行为与上面的查询不同,如果在 Perryridge 分行有多个帐户或多个贷款,它将返回客户行的多个副本。GROUP BY我们可以通过包含一个子句轻松消除这些重复项。

SELECT c.name
  FROM customer c
  JOIN account a
    ON a.customer_id = c.id
   AND a.branch = 'Perryridge'
  JOIN loan l
    ON l.customer_id = c.id
 GROUP BY c.id

没有关于您的架构的任何信息,我在这里做了一些假设,即该列id是表的主键customer,并且 theaccountloan表都有一个外键customer_idcustomer(id)等等。

这些查询中的每一个都将表现出不同的性能特征。所有查询都可能受益于索引

... ON account (customer_id, branch)
... ON loan (customer_id)
... ON customer (id, name)

这应该足以回答您的问题。


更新:

给予(比利)

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

(这似乎更像是一个学术作业或测试问题,而不是由 IT 专业人员设计和实施的数据库。)

获取在 'Perryridge' 分店depositor拥有的客户名称 ( ):account

SELECT d.customer_name
  FROM depositor d
  JOIN account a
    ON a.account_number = d.account_number
 WHERE a.branch_name = 'Perryridge'
 GROUP BY d.customer_name

获取在 'Perryridge' 分店borrower拥有的客户名称 ( ):loan

SELECT b.customer_name
  FROM borrower b
  JOIN loan l
    ON l.loan_number = b.loan_number
   AND l.branch_name = 'Perryridge'
 GROUP BY b.customer_name

(如果我们需要表中的其他列customer,我们将向该表添加一个 JOIN:

SELECT c.customer_name
     , c.customer_street
     , c.customer_city
  FROM customer c
  JOIN borrower b
    ON b.customer_name = c.customer_name
  JOIN loan l
    ON l.loan_number = b.loan_number
   AND l.branch_name = 'Perryridge'
 GROUP
    BY c.customer_name
     , c.customer_street
     , c.customer_city

获取在 'Perryridge' 分行同时拥有存款账户 ( depositor) 和贷款 ( ) 的客户姓名:borrower

SELECT c.customer_name
     , c.customer_street
     , c.customer_city
  FROM customer c
  JOIN borrower b
    ON b.customer_name = c.customer_name
  JOIN loan l
    ON l.loan_number = b.loan_number
   AND l.branch_name = 'Perryridge'
  JOIN depositor d
    ON d.customer_name = c.customer_name
  JOIN account a
    ON a.account_number = d.account_number
   AND a.branch_name = 'Perryridge'
 GROUP
    BY c.customer_name
     , c.customer_street
     , c.customer_city
 ORDER
    BY c.customer_name
     , c.customer_street
     , c.customer_city

使用带有相关子查询的 EXISTS 谓词的查询可以返回几乎相同的结果集。(不同的是,当客户在 Perryridge 拥有多个账户或多个贷款时,上面的 JOIN 查询可以引入“重复”。那里的 GROUP BY 子句消除了重复。)

SELECT c.customer_name
     , c.customer_street
     , c.customer_city
  FROM customer c
 WHERE EXISTS 
       ( SELECT 1
           FROM borrower b
          WHERE b.customer_name = c.customer_name
            AND EXISTS
                ( SELECT 1
                    FROM loan l
                   WHERE l.loan_number = b.loan_number
                      AND l.branch_name = 'Perryridge'
                )
       )
   AND EXISTS
       ( SELECT 1
           FROM depositor d
          WHERE d.customer_name = c.customer_name
            AND EXISTS
                ( SELECT 1
                    FROM account a
                   WHERE a.account_number = d.account_number
                     AND a.branch_name = 'Perryridge'
                )
       )
 ORDER
    BY c.customer_name
     , c.customer_street
     , c.customer_city

此查询不会引入任何重复项,因为它只返回customer表中的行。(此查询返回重复项的唯一方法是表中是否存在重复行customer。)如果表中没有重复行customer,则不需要 GROUP BY。

于 2012-12-27T20:35:59.127 回答