SQL计算日期范围数量

4

我想查询我的SQL数据库,以获取在特定日期范围内每个客户的订单数量。

我有以下订单清单

CustomerName       ClientID        DateOrdered
Customer No.2         10            2011-11-25
Customer No.3         11            2011-10-15
Customer No.3         11            2011-11-25

我希望能够查询特定客户在2011年11月1日至2011年11月30日期间的订单数量,结果应如下所示:

CustomerName       ClientID        Number
Customer No.3         11             1
Customer No.2         10             1

到目前为止,我已经成功实现了这个。
SELECT CustomerName, ClientID, COUNT(*) AS Number      
FROM Orders t     
GROUP BY CustomerName, ClientID      
HAVING COUNT(*) =      
(SELECT MAX(Number)         
FROM          
(SELECT CustomerName, ClientID, COUNT(*) AS Number             
FROM Orders            
GROUP BY CustomerName, ClientID ) x       
WHERE CustomerName = t.CustomerName )

这让我获得了客户曾经下过的所有订单

CustomerName       ClientID        Number
Customer No.3         11             2
Customer No.2         10             1

我这样解决问题的方式是否正确,还是有更简单的方法我完全忽略了?


超出主题:为什么在订单表中有客户ID和客户名称?如果您需要任何其他客户信息,您将不得不与客户表连接。如果您输错了客户名称并进行更正,则还需要修改订单表。因此,只有外键客户ID会更准确... - luso
它实际上不应该在那里!谢谢您提醒我将其删除 :) - kiwijus
4个回答

9
应该可以正常工作:
select CustomerName, ClientID, count(*) as Number
from Orders
where DateOrdered between '20111101' and '20111130'
group by CustomerName, ClientID

@MichaelPowaga,为什么要使用子查询? - user359040
@MarkBannister,这并不是必须的,但在执行计划中没有任何变化(至少在我的情况下)。 - Michał Powaga
@MichaelPowaga,那么为什么要使用它呢? - user359040
@MarkBannister,你在这种情况下是正确的,子查询是无用的。我已经将其删除。 - Michał Powaga

6
select CustomerName, ClientID, count(*)
from
(
    select CustomerName, ClientID
    from Orders
    where datediff(mm, DateOrdered, getdate()) <= 1
 )a
group by CustomerName, ClientID

这个查询使用子查询来按给定月份的日期过滤行(这似乎是您要寻找的内容)。然后,它根据客户名称和客户ID进行分组,并获取其订单总数。

@kiwijus 很高兴能帮忙!请点击此帖子的勾选标记将此答案标记为“已接受”。 :) - user596075
sum 的意思是什么?它在 SQL Server 中真的有效吗? datediff(mm, DateOrdered, getdate()) - 如果索引可用,它会使用索引吗? - Michał Powaga
只是出于好奇,为什么在这种情况下使用datediff会比between更好呢? - SimaPro

1
select ClientID, max(CustomerName), count(*) 
from Orders 
where DateOrdered between '2011-11-01' and '2011-11-30'
group by ClientID

根据数据库的不同,DateOrdered选择语句的语法可能需要有所变化。


如果您的变量格式为(Y-m-d),请不要忘记添加“start_date 00:00:00”和“end_date 23:59:59”。 - luso
这个问题只涉及日期,没有时间,否则我会写成... DateOrdered >= '2011-11-01' and DateOrdered < '2011-12-01'。一个订单可能发生在23:59:59.1,这将被between语法所忽略。 - user359040
1
对于日期范围,最好使用 DateOrdered >= '2011-11-01' AND DateOrdered < '2011-12-01'。通过使结束日期变为排除性的(使用 <),您就不需要关心日期字段是否包含时间。 - MatBailie
我从来没有真正理解这个问题的关键,但有不止一次因为这个问题陷入了麻烦。我从未调查过它,但它总是能够工作。 :D - luso

1
SELECT
  c.CustomerName,
  count(o.OrderID) as Orders
FROM
  orders o
JOIN clients c ON o.ClientID = c.ClientID
WHERE
  o.DateOrdered BETWEEN '2011-11-01' AND '2011-11-20'
GROUP BY c.ClientID ;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接