2016-03-06 3 views
1

Я следующий SQL заявление:T SQL DATEPART и граф - Показать также недели с нулевым кол

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 заказами?

+0

У вас есть время таблицу, содержащую соответствующие даты? – sagi

+0

@sagi Что значит «соответствующие даты»? Я хочу подсчеты на все недели в течение года, даже если это ноль – mJay

ответ

2

Gofr1 был на правильном пути, но есть проблемы с запросом.

1 - Вы не хотите использовать latefix() начала и конца в качестве условия остановки. Он работает целый год, но не будет работать для частичных диапазонов.

2 - Я бы добавил год к ключу, так как это позволит вам обрабатывать случаи с кросс-годами.

3 - Вам необходимо свернуть продажи перед использованием общей таблицы выдержки года. В противном случае вы просто выбросите нули снова (укажите даты) с предложением WHERE.

Помните, что логически соединение применяется, а затем предложение where.

Код ниже использует базу данных DW Adventure Works 2012 и получает правильный ответ.

  • Использует таблицу подсчета для некоторых чисел.
  • Генерирует еженедельные даты и вычисляет ключ год/неделя для заданного диапазона.
  • Свертывает продажи из таблицы фактов для заданного диапазона.
  • Левый соединяет ключи с продажами и обнуляет нулевые значения.

Код:

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

enter image description here

+0

. Ваш ответ кажется гораздо более точным, поэтому я удаляю мой :) Возьмите upvote! – gofr1

+0

Еще один комментарий. Так как вам никогда не понадобится 200k номеров, перейдите sys.types с sys.all_views, чтобы получить 14.5K номеров. Это поможет с общим временем выполнения. –

+0

Большое спасибо. Я действительно думал, что есть простой способ в SQL ... кажется, я ошибался :) Я приму свой подход – mJay