and*_*rea 0 sql-server subquery greatest-n-per-group
我有这张表,我想检索下订单数量最多的客户。
我写了这个查询:
select * from customers where cust_id=(
select cust_id from orders
group by cust_id
having count(*)>=all(select count(cust_id)
from orders
group by cust_id))
Run Code Online (Sandbox Code Playgroud)
我知道也许有更好的方法来做到这一点,但我惊讶地发现 'ALL' 可以与 '> =' 一起使用
根据我的理解,'ALL' 检查当前行是大于还是小于子查询中的所有行,但我从没想过可以将它与 '=' 一起使用。
如果我将它与 '=' 或 '>' 一起使用,查询不会像我期望的那样返回任何行。
但是如果我将它们一起使用 '>=' 查询会给我正确的结果。
是不是很奇怪?
无论如何,最后我写了这个查询:
SELECT *
FROM Orders, customers
WHERE orders.cust_id=customers.cust_id
and orders.cust_id IN
(SELECT TOP (1) o.cust_id
FROM Orders AS O
GROUP BY O.cust_id
ORDER BY COUNT(*) DESC);
Run Code Online (Sandbox Code Playgroud)
你有更好或更优雅的解决方案吗?
在 'ALL' 子句中使用 '>=' 是不是很奇怪?
谢谢你。
各种写法。您的查询,稍微改写以使用JOIN
并更正以在出现联系时返回所有客户:
select c.*, o.*
from customers as c
join orders as o
on o.cust_id = c.cust_id
where c.cust_id in
( select cust_id
from orders
group by cust_id
having count(*) >=
all ( select count(*)
from orders
group by cust_id
)
) ;
Run Code Online (Sandbox Code Playgroud)
类似,不使用>= ALL
:
select c.*, o.*
from customers as c
join orders as o
on o.cust_id = c.cust_id
where c.cust_id in
( select cust_id
from orders
group by cust_id
having count(*) =
( select top (1) count(*) as cnt
from orders
group by cust_id
order by cnt desc
)
) ;
Run Code Online (Sandbox Code Playgroud)
子查询简化为TOP WITH TIES
:
select c.*, o.*
from customers as c
join orders as o
on o.cust_id = c.cust_id
where c.cust_id in
( select top (1) with ties m.cust_id
from orders as m
group by m.cust_id
order by count(*) desc
) ;
Run Code Online (Sandbox Code Playgroud)
以上所有内容都可以重写为使用派生表或 CTE,并且JOIN
子查询是不相关的。
另一种方法是结合使用窗口函数TOP
:
with
d as
( select c.*, o.*,
cnt = count(*) over (partition by o.cust_id)
from customers as c
join orders as o
on o.cust_id = c.cust_id
)
select top (1) with ties
d.*
from d
order by d.cnt desc ;
Run Code Online (Sandbox Code Playgroud)
或者只是窗口函数:
with
d as
( select m.cust_id,
cnt = count(*)
max_cnt = max(count(*)) over ()
from orders as m
group by m.cust_id
)
select c.*, o.*
from customers as c
join orders as o
on o.cust_id = c.cust_id
join d
on d.cust_id = c.cust_id
where d.cnt = d.max_cnt ;
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1872 次 |
最近记录: |