2015-06-17 4 views
2

У меня есть таблица, которая отображает хиты на ссылку на каждый день длинного со столбцом «происхождения»Как запрашивать данные за каждый x месяц в SQL?

hitdate  originid hitcount 
================================== 
2011-01-05   2   25 
2011-01-05   3   3 
2011-04-06   2   1   
2011-04-06   6   11 
2011-05-06   7   9 
2011-05-09   2   25 
2011-07-10   3   3 
2011-17-11   2   1   
2011-01-12   6   11 
2012-01-06   7   9 

То, что я хочу, чтобы программно просуммировать HitCount за каждые 3 месяца, для каждого originID, так как в первый день набора (который является 1 мая 2011 года) до сегодняшнего дня

результаты, которые я хочу получить

Trimester     originid hitcount 
============================================== 
2011-01-05 to 2011-31-07   1   0 
           2   26 
           3   3 
           6   11 
2011-01-08 to 2011-31-10  ..   .. 
+0

Важнейшая часть отсутствует. Вы хотите слить годы? –

ответ

2

Я думаю, возможный источник проблем с использованием datepart(qq, ..., поскольку другие ответы заключаются в том, что (1) это, похоже, не учитывает возможность установки даты, охватывающей несколько лет, и (2) она делает предположения о самой ранней дате в вашем наборе данных , Я попытался написать решение, которое будет работать для любой даты начала, даже если это не первый день месяца. Это немного сложнее, поэтому, возможно, кто-то может предложить способ упростить его.

-- Sample data from the question. 
declare @hits table (hitdate date, originid bigint, hitcount int); 
insert @hits values 
    (convert(date, '20110501', 112), 2, 25), 
    (convert(date, '20110501', 112), 3, 3), 
    (convert(date, '20110604', 112), 2, 1), 
    (convert(date, '20110604', 112), 6, 11), 
    (convert(date, '20110605', 112), 7, 9), 
    (convert(date, '20110905', 112), 2, 25), 
    (convert(date, '20111007', 112), 3, 3), 
    (convert(date, '20111117', 112), 2, 1), 
    (convert(date, '20111201', 112), 6, 11), 
    (convert(date, '20120601', 112), 7, 9); 

-- Define the date range that we're concerned with. 
declare @beginDate date, @endDate date; 
select 
    @beginDate = min(hitdate), 
    @endDate = convert(date, getdate()) 
from 
    @hits; 

-- Build a list of three-month periods that encompass the date range defined 
-- above. Each period will be inclusive on the lower end of the range and 
-- exclusive on the upper end. 
declare @Trimester table (beginDate date, endDate date); 
while @beginDate <= @endDate 
begin 
    insert @Trimester values (@beginDate, dateadd(m, 3, @beginDate)); 
    set @beginDate = dateadd(m, 3, @beginDate); 
end; 

-- Finally, assign each hit to one of these periods. 
select 
    [Trimester] = 
     convert(varchar, T.beginDate) + 
     ' to ' + 
     convert(varchar, dateadd(d, -1, T.endDate)), 
    H.originid, 
    hitcount = sum(H.hitcount) 
from 
    @hits H 
    inner join @Trimester T on 
     H.hitdate >= T.beginDate and 
     H.hitdate < T.endDate 
group by 
    T.beginDate, 
    T.endDate, 
    H.originid 
order by 
    T.beginDate, 
    H.originid; 

Результирующий набор:

Query results

Одно различие между моим результатом установить и у вас, что ваша содержит запись о том, что были нулевые хиты для originid = 1. Я ничего не сделал с этим, так как я не знаю, где вы храните набор допустимых значений originid, но вам должно быть довольно легко настроить этот запрос, чтобы поддержать это, если хотите, просто вмешавшись в присоединяется к заключительному этапу.

Update: Чуть больше моих проблем с использованием datepart:

  • Использование datepart(qq, hitdate) само по себе предполагает, что границы квартала календарные кварталы, например, 1 апреля-30 июня, как уже было отмечено в другом ответе.

  • С помощью чего-то вроде datepart(qq, dateadd(mm,1,hitdate)) сдвигает квартал на месяц, поэтому вы начинаете 1 мая, как в ваших данных образца, но предположите, что хотите начать в июне, а не в мае. Вы должны изменить запрос.

  • datepart(qq, ... само по себе будет возвращать то же значение для двух дат, которые находятся в том же квартале, но в разные годы. Таким образом, хиты 1 мая 2011 года и 1 мая 2012 года будут сгруппированы вместе. Вы можете приспособиться к этому, но на момент написания этой статьи другие ответы не поступают.

  • Использование datepart любым из способов, описанных выше, предполагает, что кварталы начинаются в первый день месяца. Предположим, что самая ранняя дата в вашем результирующем наборе была 15 мая. Мой запрос будет обрабатываться 15 мая-14 августа как первый квартал, 15 августа-14 ноября, как второй квартал и т. Д.

Это последнее, я думаю, может быть наиболее трудно преодолеть, если вы хотите, решение, которое использует datepart(qq, ...). Если вам будет удобно предположить, что дата начала - это первый день месяца, то возможно более простое решение, чем я предложил.

В запросе выше, если вы хотите использовать другую дату начала, вы просто назначаете дату, которую вы хотите, @beginDate.

+0

Спасибо, я пробовал все предлагаемые решения, и ваши данные дают точные результаты с использованием datepart (qq, hitdate), все являются правильными ответами, но я все еще путаюсь, почему использование datepart (qq, ..) делает предположения о самой ранней дате в наборе данных. Вы имеете в виду, если даты не упорядочены должным образом? Что делать, если я хочу указать свою дату начала? –

+0

@BillyBlaze, я обновил ответ с некоторыми подробностями о ваших вопросах. Извините, что сначала неясно. –

+0

Farell, спасибо, теперь имеет больше смысла. Ваше решение более гибкое. –

1

Использование Group BY и DATEPART

SELECT DATEPART(qq,hitdate) AS Trimester, originid, SUM(hitcount) 
FROM yourtable 
GROUP BY DATEPART(qq,hitdate), originid 
+0

Понравилась эта группа по месяцам? Не триместр? –

+0

@BrianMikeyHalbert мой плохой, отредактированный – Matt

1

Используйте DATEPART, чтобы разбить дату на четверти. Как ваши 3 месяца периоды не являются стандартными четверти (январь-март, апрель-июнь), вы можете использовать DATEADD для того, чтобы компенсировать ваши hitdate так, что она попадает в соответствующий три месяца:

Select DATEPART(qq,dateadd(mm,1,hitdate)) as QRTR, originid, SUM(hitcount) 
from tablename 
group by DATEPART(qq,dateadd(mm,1,hitdate)), originid 
Смежные вопросы