【问题标题】:select all users that have only one order and that order meets some criteria选择所有只有一个订单并且该订单满足某些条件的用户
【发布时间】:2012-12-05 13:12:53
【问题描述】:

我的表格包含这样的用户:

user_id | status
----------------
1       | 1
2       | 2
3       | 1
4       | 1

包含订单的表格

order_id | user_id | status
---------------------------
1        | 1       | 1
2        | 2       | 1
3        | 2       | 2
4        | 2       | 1
5        | 3       | 1

以及包含订购产品的表格

order_id | cash
----------------
1        | 10
1        | 20
1        | 10
2        | 10
3        | 10
3        | 10

我需要选择的是所有状态为 1 且只有一个订单且该订单的状态必须为 1 且该订单的所有产品总和必须 >=30 的用户。

所以对于上述数据查询应该只返回 id=1 的用户

我已经设法编写了选择过程,但它运行不快:

SELECT user_id
FROM   users US
WHERE  status = 1
       AND (SELECT Count(*)
            FROM   orders ORD
            WHERE  ORD.user_id = US.user_id) = 1
       AND (SELECT Count(*)
            FROM   orders ORD
            WHERE  ORD.user_id = US.user_id
                   AND ORD.status = 1) = 1
       AND (SELECT Sum(PRO.cash)
            FROM   products PRO
                   JOIN orders ORD
                     ON PRO.order_id = ORD.order_id
            WHERE  ORD.user_id = US.user_id) > 30  

我想稍微改进一下,这样我就不必使用太多内部选择了

【问题讨论】:

    标签: sql tsql sql-server-2005


    【解决方案1】:

    您通常可以通过将查询从where 子句移动到joins 来获得更好的性能:

    select  u.user_id
    from    Users u
    join    Orders o
    on      o.user_id = u.user_id
    join    Producs p
    on      p.order_id = o.order_id
    group by
            u.user_id
    having  min(u.status) = 1 -- there's only 1 user, so min() is safe
            and count(distinct o.order_id) = 1
            and min(o.status) = 1 -- there's only 1 order, so min() is safe
            and sum(p.cash) > 30
    

    【讨论】:

    • +1 子选择反映了对 OP 约束的很好理解。学习了一些关于将 min 用于 having 子句的知识。
    • 我什至没想过这样查询 :) 我会马上检查 :)
    【解决方案2】:
    SELECT USER_ID
      FROM (SELECT US.USER_ID, SUM (PRO.CASH) CASH
              FROM USERS US, ORDERS ORD, PRODUCTS PRO
             WHERE US.USER_ID = ORD.USER_ID AND ORD.ORDER_ID = PRO.ORDER_ID AND US.STATUS = 1 AND ORD.STATUS = 1)
     WHERE CASH > 30
    

    【讨论】:

    • 我喜欢您使用子选择来回答问题。 OP 还对“恰好一个订单”和“状态 = 1”有限制
    • 这将返回一个有两个订单的用户,其中一个状态 = 0,另一个状态 = 1
    猜你喜欢
    • 2014-07-17
    • 1970-01-01
    • 1970-01-01
    • 2018-01-06
    • 2013-04-13
    • 2017-07-08
    • 2021-08-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多