【问题标题】:T SQL Datepart and Count - Show also weeks with zero countT SQL Datepart and Count - 也显示周数为零
【发布时间】:2016-03-06 16:21:04
【问题描述】:

我有以下 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 个订单的周数?

【问题讨论】:

  • 您有包含相关日期的时间表吗?
  • @sagi “相关日期”是什么意思?我想要一年中所有周的计数,即使它为零

标签: sql sql-server tsql count datepart


【解决方案1】:

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

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

2 - 我会在键中添加年份,因为这样可以让您处理跨年份的案例。

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

请记住,逻辑上先应用连接,然后应用 where 子句。

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

  • 对某些数字使用计数表。
  • 生成每周日期并计算给定范围的年/周键。
  • 从事实表中汇总给定范围的销售额。
  • Left 将键连接到销售并将空总计变为零。

代码:

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

【讨论】:

  • 你的答案似乎更准确,所以我删除了我的:) 投赞成票!
  • 只有一条评论。由于您永远不需要 200k 数字,因此将 sys.types 与 sys.all_views 交叉以得出 14.5K 数字。这将有助于缩短整体执行时间。
  • 非常感谢。我真的认为在 SQL 中有一种更简单的方法......似乎我错了:) 我会采用你的方法
  • 加快速度的一种方法是创建一个静态表,其中包含所有关注周的 yyyyww。这将消除前两个公用表表达式。也许添加一个键。同样,小表上的键可能不会提高性能,因为可以将表读入内存(页)。简而言之,您始终必须使用包含数据的驱动程序表来连接到可能没有数据的表(分组)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-09
相关资源
最近更新 更多