【问题标题】:Create view (Exists or in) [closed]创建视图(存在或存在)[关闭]
【发布时间】:2012-12-27 20:08:25
【问题描述】:

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

对此有什么想法吗?我很困惑是使用exists还是in


这些表格是:

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)

【问题讨论】:

  • 视图基本上是选择的结果。一旦你弄清楚选择应该是什么,你就可以拥有视图。我不完全理解您所说的“使用存在或存在”是什么意思
  • 没有足够的信息来回答这个问题。我投票结束。

标签: mysql


【解决方案1】:

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

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

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

作为示例,此查询(如下)使用EXISTS 谓词来测试account 表和loan 表中是否存在匹配行,并从customer 返回至少具有Perryridge 分行的一个关联账户,以及至少一笔关联贷款。

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 谓词来查找帐户和贷款表中的匹配行:

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 表的主键,并且 accountloan 表都有一个外部关键customer_id引用customer(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”分店拥有account 的客户的姓名 (depositor):

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”分店拥有loan 的客户的姓名 (borrower):

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。

【讨论】:

  • 分行(branch_name, branch_city, assets) 客户(customer_name, customer_street, customer_city) 账户(account_number, branch_name, balance) 贷款(loan_number, branch_name, amount) 存款人(customer_name, account_number) 借款人(customer_name,贷款号码)
  • @Billy,此信息可能会更好地包含在您的问题中,而不是作为对我的回答的评论。
猜你喜欢
  • 1970-01-01
  • 2019-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-15
  • 1970-01-01
  • 2011-03-20
  • 1970-01-01
相关资源
最近更新 更多