【问题标题】:Is there more efficient way to write this sql query?有没有更有效的方法来编写这个 sql 查询?
【发布时间】:2015-01-11 11:44:01
【问题描述】:

我需要在下面的 2 个表上编写一个有效的查询,条件如下表: 第一个表

CityCode    CustomerID  AccountID 
Paris       1           1
Roma        2           1
London      1           2
Paris       3           2
Roma        4           3
Berlin      5           4

第二张桌子

Credit_card_ind Credit  AccountID 
0               1000    1
1               5000    2
0               2300    3
1               30000   4

0 - 没有卡
1 - 有一张卡片

在查询中,我们需要以下条件:
1.所有信用在5000以上的客户
2. 不显示其中一位客户没有信用卡的帐户
3.所有信用低于30000的账户
4. 不显示其中一位客户来自“罗马”的帐户
5. 显示拥有超过 1 个客户的帐户。

(*) - 可能没有记录返回。

我按如下方式编写查询,我想确认它是这样做的最佳方式,其目的是减少我们接近表和执行联接的次数

Select  c.AccountID,
        c.CustomerID        
From    Customers as c 
Join    credit_cards as ca on c.AccountID = ca.AccountID
Where   ca.credit > 5000 And ca.credit < 30000
And     c.AccountID not in  (
                            Select  Distinct newTBL.AccountID
                            From    (
                                    Select  c1.CustomerID,
                                            c1.AccountID
                                    From    customers as c1
                                    Join    credit_cards as ca1 on c.AccountID = ca.AccountID
                                    Where   ca1.credit_card_ind = 0
                                    Or  c1.CityCode like ‘Roma’
                                    ) as newTBL
                            )
And    c.AccountID in ( 
                        Select  newCus.AccountID
                        From    (
                                Select  AccountID,
                                        Count(CustomerID) as [Num_of_Cus]
                                From customers
                                Group by AccountID
                                ) as newCus
                        Where newCus.[Num_of_Cus] > 1
                        )

【问题讨论】:

  • 给出长查询的输出,这样其他人就可以看到您正在尝试做什么以及您是如何做的,而不仅仅是您如何做。
  • 你没有显示城市代码,没有通配符,你也可以使用equal='Roma',对于通配符(如果不需要,查找速度会更慢)你想要一个perent LIKE 'Roma%' .更好的是,如果城市 Roma 有一个 id,那么整数匹配查询会更快。
  • 哪个数据库?例如,not in 在 Oracle 中非常高效,但在 MySQL 中却是性能杀手。
  • sql server(感谢评论,不知道......虽然效率是通过逻辑查询而不是语法来衡量的)城市代码没有整数代码,它是一个文本字段。

标签: sql sql-server


【解决方案1】:

首先,您可以通过删除嵌套子查询来简化查询:

Select  c.AccountID, c.CustomerID        
From    Customers c Join
        credit_cards ca
        on c.AccountID = ca.AccountID
Where   ca.credit > 5000 And ca.credit < 30000 And
        c.AccountID not in  (Select  c1.CustomerID
                             From customers c1 Join
                                  credit_cards ca1
                                  on c.AccountID = ca.AccountID
                             Where  ca1.credit_card_ind = 0 Or c1.CityCode like 'Roma'
                            ) And
        c.AccountID in (Select AccountID
                        From customers
                        Group by AccountID
                        Having Count(CustomerID) > 1
                       );

这可能会有所帮助。您也可以使用窗口函数来编写它,这可能更有效。我认为以下查询捕获了您的原始条件:

select c.AccountID, c.CustomerID 
from (select c.*, count(*) over (partition by c.accountid) as cnt,
             max(case when c.CityCode like 'Roma' then 1 else 0 end) as cnt_Roma
      from customers c
     ) c join
     credit cr
     on c.accountid = cr.accountid
where ca.credit > 5000 And ca.credit < 30000 and
      c.cnt > 0 and c.cnt_Roma = 0 and
      ca.credit_card_ind <> 0;

【讨论】:

    【解决方案2】:

    试试这个。

    SELECT cs.AccountID
    FROM   customer cs
           JOIN credit cr
             ON cs.AccountID = cr.AccountID
    WHERE  CityCode <> 'Roma'
           AND Credit_card_ind = 1
           AND Credit > 5000
           AND Credit < 30000
    GROUP  BY cs.AccountID
    HAVING Count(cs.CustomerID) > 1 
    

    【讨论】:

    • 感谢您的回复,虽然它不好,因为在一般情况下,查询将返回一个帐户的记录,其中 1.credit 值正在回答限制 2.两个客户中的一个有一个信用,其中第二个客户没有。 3.客户不是来自“罗马”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多