T SQL Datepart和Count-也显示周数为零

T SQL Datepart和Count-也显示周数为零,sql,sql-server,tsql,count,datepart,Sql,Sql Server,Tsql,Count,Datepart,我有以下SQL语句: declare @dateFrom datetime = '2015-01-01'; declare @dateTo datetime = '2015-12-31'; select DATEPART(WEEK, OrderDate) Week, Count(*) Number from table where OrderDate between @dateFrom and @dateTo group by DATEPART(

我有以下SQL语句:

declare @dateFrom datetime = '2015-01-01'; 
declare @dateTo datetime = '2015-12-31'; 

select 
    DATEPART(WEEK, OrderDate) Week, Count(*) Number
from 
    table 
where 
    OrderDate between @dateFrom and @dateTo 
group by 
    DATEPART(WEEK, OrderDate) 
order by 
    Week
它返回每周的订单数量,但如果没有订单,则忽略相应的一周


如何更改该报表,使其也包括周和0个订单

Gofr1在正确的轨道上,但查询存在问题

1-您不希望使用开始和结束的datediff作为停止条件。它可以工作一整年,但不适用于部分范围

2-我会在密钥中添加年份,因为这将允许您处理跨年度的案例

3-在使用年-周通用表表达式之前,需要汇总销售额。否则,您只需再次抛出带有WHERE子句的空订单日期

记住,从逻辑上讲,连接应用于where子句

下面的代码使用Adventure Works 2012 DW数据库并获得正确答案

对一些数字使用计数表。 生成每周日期并计算给定范围的年/周关键字。 从给定范围的事实表中汇总销售额。 Left将键连接到sales,并将null总计变为零。 代码:


你有包含相关日期的时间表吗?@sagi“相关日期”是什么意思?我想要一年中所有星期的计数,即使是零。你的答案似乎更准确,所以我删除了我的:投票!再多说一句。因为您永远不需要200000个数字,所以将sys.types与sys.all_视图交叉,得到14.5K的数字。这将有助于总的执行时间。非常感谢。我真的认为在SQL中有一种更简单的方法…似乎我错了:我将采用您的方法一种使它更快的方法是创建一个静态表,该表包含所有感兴趣的周的yyyyww。这将消除前两个常用的表表达式。也许加一把钥匙。同样,小表上的键可能不会提高性能,因为表可以读入内存页。简言之,您必须始终使用一个驱动程序表,该驱动程序表包含要连接到可能不包含数据的表分组的数据。
-- Declare start and end date
DECLARE @dte_From datetime = '2005-07-01'; 
DECLARE @dte_To datetime = '2007-12-31'; 

-- About 200K numbers
WITH cte_Tally (n) as
(
    SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
    FROM sys.all_views a 
    CROSS JOIN sys.all_views b
),

-- Create year/week key
cte_YearWeekKey (MyKey) as
(
SELECT 
    year(dateadd(week, t.n, @dte_from)) * 1000 + 
    datepart(week, dateadd(week, t.n, @dte_from)) as MyKey
FROM 
    cte_Tally as t
WHERE 
    dateadd(week, t.n, @dte_from) < @dte_To
),

-- Must roll up here
cte_Sales (MyKey, MyTotal) as
(
SELECT 
    YEAR(F.OrderDate) * 1000 +
    DATEPART(WEEK, F.OrderDate) as MyKey, 
    COUNT(*) as MyTotal
FROM
    [AdventureWorksDW2012].[dbo].[FactResellerSales] F
WHERE 
    F.OrderDate between @dte_From and @dte_To 
GROUP BY 
    YEAR(F.OrderDate) * 1000 +
    DATEPART(WEEK, F.OrderDate)
)

-- Join the results
SELECT 
    K.MyKey, ISNULL(S.MyTotal, 0) as Total
FROM
    cte_YearWeekKey as K
LEFT JOIN 
    cte_Sales as S
ON 
    k.MyKey = S.MyKey