Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/87.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 选择只有一个订单且该订单满足某些条件的所有用户_Sql_Tsql_Sql Server 2005 - Fatal编程技术网

Sql 选择只有一个订单且该订单满足某些条件的所有用户

Sql 选择只有一个订单且该订单满足某些条件的所有用户,sql,tsql,sql-server-2005,Sql,Tsql,Sql Server 2005,我有一个包含如下用户的表: 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 |

我有一个包含如下用户的表:

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过程,但运行速度不快:

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  

我想对此做一点改进,这样我就不必使用太多的内部选择

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

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
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

通常,通过将查询从
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

我喜欢你用副词来回答这个问题。OP还对“恰好一个订单”和“状态=1”进行了限制。这将返回一个用户两个订单,其中一个订单的状态=0,另一个订单的状态=1I,就像您使用subselect来回答问题一样。OP也有“恰好一个订单”和“状态=1”的约束。这将返回一个用户两个订单,其中一个订单的状态=0,另一个订单的状态=1+1。子选择反映了对OP约束的良好理解。了解了使用min作为having子句的一些内容。我甚至没有想过用这种方式执行查询:)我马上检查:)+1子选择反映了对OP约束的良好理解。了解了如何使用min作为having子句。我甚至没有想过用这种方式执行查询:)我马上检查:)