使用join的高级sql查询

时间:2015-06-08 15:45:15

标签: sql database

概念银行业务示例

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)

查找在布鲁克林所有分支机构拥有帐户的所有客户。

select distinct S.customer-name 
   from depositor as S 
   where not exists (
   (select branch-name 
     from branch where branch-city = ‘Brooklyn’)
   except
   (select R.branch-name 
    from depositor as T, account as R 
    where T.account-number = R.account-number 
      and S.customer-name = T.customer-name)
   )

我发现以下查询难以理解。有人请解释背后的逻辑吗?

3 个答案:

答案 0 :(得分:3)

因此,您要从customer-name表格中选择depositor,其中:

  1. 你在布鲁克林的所有分支机构获得branch-name(select branch-name from branch where branch-city = ‘Brooklyn’)
  2. 您正在获取布鲁克林的所有branch-name个特定客户的帐户:(select R.branch-name from depositor as T, account as R where T.account-number = R.account-number and S.customer-name = T.customer-name)
  3. 你从1中{1}来减去(减去)2中的值。例如,如果" Best branch"在2中,它将从1的结果中删除(如果它也在那里)。
  4. 您希望EXCEPT获得3的结果。也就是说,您希望步骤3中的减法不会留下任何内容。所有来自1的分支也应该也是为了让顾客打印出他/她的名字,他已经2岁了。
  5. <强>实施例

    假设布鲁克林有三家分店:&#34; Best&#34;,&#34; Average&#34;和#34;最糟糕的&#34;。

    Bob 进入&#34; Best&#34;和&#34;平均&#34;。

    1. 所有分支机构:&#34; Best&#34;,&#34; Average&#34;,&#34; Worst&#34;
    2. Bob去的分支:&#34; Best&#34;,&#34; Average&#34;
    3. 2 - 1:&#34; Best&#34;,&#34; Average&#34;,&#34; Worst&#34;减去&#34;最佳&#34;,&#34;平均&#34;。这使我们只能使用&#34; Worst&#34;
    4. NOT EXISTS - 等一下,我们仍然有#34;最糟糕的&#34;!有东西存在!这意味着此条件的评估结果为NOT EXISTS
    5. 鲍勃未被选中。

      玛丽仅进入&#34; Best&#34 ;.

      1. 所有分支机构:&#34; Best&#34;,&#34; Average&#34;,&#34; Worst&#34;
      2. Bob去的分支:&#34; Best&#34;
      3. 2 - 1:&#34; Best&#34;,&#34; Average&#34;,&#34; Worst&#34;减去&#34;最佳&#34;。这给我们带来了#34;平均&#34;,&#34; Worst&#34;
      4. false - 等一下,我们仍然有&#34;平均&#34;和#34;最糟糕的&#34;!有东西存在!这意味着此条件的评估结果为NOT EXISTS
      5. 玛丽未被选中。

        忙碌的人进入&#34; Best&#34;,&#34; Average&#34;和#34;最糟糕的&#34;。

        1. 所有分支机构:&#34; Best&#34;,&#34; Average&#34;,&#34; Worst&#34;
        2. Bob去的分支:&#34; Best&#34; &#34;平均&#34;,&#34;最差&#34;
        3. 2 - 1:&#34; Best&#34;,&#34; Average&#34;,&#34; Worst&#34;减去&#34;最佳&#34;,&#34;平均&#34;,&#34;最差&#34;。这让我们......没什么
        4. false - 那是对的!我的意思是...... NOT EXISTS!什么都不存在
        5. 忙碌的人选中。

答案 1 :(得分:2)

注意:如果对查询进行格式化以便更容易阅读,那么理解查询可能会更容易。

-- get the unique customer names
select distinct S.[customer-name] 
--from all all depositors
    from depositor as S 
--where there the are no brooklyn branches that don't have an account for that customer
    where not exists (
    --get all brooklyn branches
    (select [branch-name]
        from branch where [branch-city] = 'Brooklyn')
    except --except removes from the set above anything in the set below
    --get all brooklyn branches that have an account for the correlated depositor
    (select R.branch-name 
        from depositor as T
        , account as R 
       where
        --this is the join condition which I would prefer to see written as ON rather than put in the WHERE 
            T.[account-number] = R.[account-number] 
        --this correlates the subsquery to the depositor
        and S.[customer-name] = T.[customer-name])
    )

答案 2 :(得分:0)

好的,让我们打破这个问题吧。首先想象你有foreach loop

1。 即想象一下,为每个客户循环执行大子查询。

select distinct S.customer-name from depositor as S 

2。 在这里,您选择布鲁克林的所有分支机构:

SELECT   branch - name
FROM     branch
WHERE    branch - city = ‘Brooklyn’

3。 在这里,您将为循环1中的特定客户选择所有分支。它是相关子查询。请注意S.customer

SELECT   R.branch - name
FROM     depositor AS T ,
        account AS R
WHERE    T.account - number = R.account - number
        AND S.customer - name = T.customer - name

现在EXCEPT将执行以下操作:它将从2开始每一行并检查它是否存在于3.如果它存在,它将从结果中抛出它。所以实际上,如果从2抛出的所有行都意味着布鲁克林的所有分支都被抛出,因为每个分支都有3个对应的行。这意味着如果客户在所有分支中都有空,他将在子查询中得到空集。外部循环将过滤掉内部子查询返回至少一行的客户,这意味着客户在至少一个分支中没有帐户。