2014-11-24 3 views
1

Я пытаюсь группировать кучу дат, времени, а именно «месяц»Группировка дат по DateAdd и DateDiff

Сначала я объявляю таблицу:

--inserts 36 dates every 10 days 
create table sales (sales_date datetime, sales_amount decimal(12,2)) 
insert into sales (sales_date,sales_amount) 
select '20140101',1000 union all 
select '20140110',1000 union all 
select '20140120',1000 union all 
select '20140130',1000 union all 
... 

затем я запрашиваю данные, сгруппированные по периодам (размером = точность * месяцев)

DECLARE @precision int = 1 --number of months 

SELECT 
dateadd(month, (datediff(month, 0, sales_date)/@precision) * @precision, 0) as FromDate, 
dateadd(month, @precision + (datediff(month, 0, sales_date)/@precision) * @precision, 0) as ToDate, 
count(*) as number 
FROM sales 
GROUP BY 
dateadd(month, (datediff(month, 0, sales_date)/@precision) * @precision, 0), 
dateadd(month, @precision + (datediff(month, 0, sales_date)/@precision) * @precision, 0) 

Результаты:

Test 1 : precision of 1 month 
From : 01/01/2014, To : 01/02/2014, number : 4 
From : 01/02/2014, To : 01/03/2014, number : 2 
From : 01/03/2014, To : 01/04/2014, number : 3 
From : 01/05/2014, To : 01/06/2014, number : 4 
From : 01/06/2014, To : 01/07/2014, number : 3 
From : 01/07/2014, To : 01/08/2014, number : 3 
From : 01/08/2014, To : 01/09/2014, number : 3 
From : 01/09/2014, To : 01/10/2014, number : 3 
From : 01/10/2014, To : 01/11/2014, number : 3 
From : 01/11/2014, To : 01/12/2014, number : 3 
From : 01/12/2014, To : 01/01/2015, number : 2 

Test 2 : precision of 2 months 
From : 01/01/2014, To : 01/03/2014, number : 6 
From : 01/03/2014, To : 01/05/2014, number : 6 
From : 01/05/2014, To : 01/07/2014, number : 7 
From : 01/07/2014, To : 01/09/2014, number : 6 
From : 01/09/2014, To : 01/11/2014, number : 6 
From : 01/11/2014, To : 01/01/2015, number : 5 

Test 3 : precision of 3 months 
From : 01/01/2014, To : 01/04/2014, number : 9 
From : 01/04/2014, To : 01/07/2014, number : 10 
From : 01/07/2014, To : 01/10/2014, number : 9 
From : 01/10/2014, To : 01/01/2015, number : 8 

Test 4 : precision of 4 months 
From : 01/01/2014, To : 01/05/2014, number : 12 
From : 01/05/2014, To : 01/09/2014, number : 13 
From : 01/09/2014, To : 01/01/2015, number : 11 

Все отлично работает до испытания 5:

Test 5 : precision of 5 months 
From : 01/10/2013, To : 01/03/2014, number : 6 
From : 01/03/2014, To : 01/08/2014, number : 16 
From : 01/08/2014, To : 01/01/2015, number : 14 

Первая строка это раздражает, мне это нужно, чтобы начать на 01/01/2014, как предыдущие точностей

Есть ли способ преодолеть эту проблему?

+0

Я не вижу, как вы получаете вывод, который вы получаете, т. Е. Я бы ожидал увидеть '' FROM: '', чтобы начать ваш список столбцов выбора, но я этого не делаю, поэтому меня ведет полагать, что есть промежуточный шаг, который вы не показываете нам здесь, и это может произойти с вашей ошибкой «перевода». –

+0

'И WHERE sales_date не является нулевым' ... эта строка не нуждается в' AND' – Tanner

+0

Результаты приходят только из моих модульных тестов на C#, но сервер sql дает совершенно то же самое; Вставка и компиляция запросов в любом случае – codablank1

ответ

0

вам не нужно делить на точность и еще раз умножить на точности для FROM колонны

вот что происходит

datediff(month, 0, sales_date)/5 -> 273.6 as it is integer division, it is converting to 273 

дальнейшего умножения его на 273*5 = 1365 (так 3 месяца теряются из-за на целое деление)

так что один должен работать для вас

DECLARE @precision int = 5 --number of months 

SELECT 
dateadd(month, (datediff(month, 0, sales_date)) , 0) as [From], 
dateadd(month, @precision + (datediff(month, 0, sales_date)) , 0) as [To], 
count(*) as number 
FROM sales 
GROUP BY 
dateadd(month, (datediff(month, 0, sales_date)) , 0), 
dateadd(month, @precision + (datediff(month, 0, sales_date)), 0) 
+0

проверить это [ссылка] (http://dba.stackexchange.com/a/17674/38687) о необходимости '/ @precision) * @ precision' ; без него есть один период в месяц – codablank1

+0

@ codablank1, затем используйте точность как 5.0 – radar

+0

@ codablank1, также у меня все еще есть точность во втором, поэтому вы получите все очки – radar

Смежные вопросы