Как сгруппировать по диапазону дат в SQL - PullRequest
2 голосов
/ 15 июня 2011

Опираясь на этот другой пост StackOverflow.com, который я нашел полезным.

Мне было интересно, можно ли группировать, используя диапазоны дат, которые я не определяю явно.

Итак, чтобы уточнить, скажем, у меня есть таблица с именем Person и столбец с именем Дата рождения.

Я бы хотел сгруппировать и подсчитать количество людей, родившихся за период.

Так бы это выглядело примерно так.

Количество рожденных

Mar1980 25

Apr1980 452

May1980 42

...

Dec1993 452

Периодом могут быть недели, месяцы и кварталы.

Если бы я использовал другое решение, мне нужно было бы указать каждый диапазон датдаже с месяцами и годами это может занять много времени, так как дата рождения людей сильно варьируется.

select t.DOB as [dob], count(*) as [number of occurences]
from (
      select user_id,
         case when date >= '1980-01-01' and date < '1980-02-01 then 'Jan 1980'
         when date >= '1980-02-01' and date < '1980-03-01 then 'Feb 1980'
         ...
         when date >= '1990-03-01' and date < '1990-04-01 then 'Mar 1990'
        else 'Null' end as DOB
     from Person) t
group by t.DOB

Есть ли какое-либо решение, которое вы можете придумать, которое может позволить мне указать только размеринтервал Я хочу, чтобы диапазоны данных были и сгруппированы по этим диапазонам дат?

Ответы [ 2 ]

1 голос
/ 15 июня 2011

Возможно, вы могли бы использовать что-то подобное и воспользоваться функцией DATEPART

Пожалуйста.не забудьте раскомментировать утверждение, которое вы хотите проверить.

WITH DummyTable AS (
SELECT '05/01/2011' AS DateOfBirth, 'Peter' AS CustomerName UNION ALL
SELECT '06/02/2011' AS DateOfBirth, 'Bill' AS CustomerName UNION ALL
SELECT '05/01/2011' AS DateOfBirth, 'Charles' AS CustomerName UNION ALL
SELECT '07/13/2010' AS DateOfBirth, 'Maria' AS CustomerName UNION ALL
SELECT '01/01/2009' AS DateOfBirth, 'Theresa' AS CustomerName UNION ALL
SELECT '05/01/2011' AS DateOfBirth, 'Steven' AS CustomerName UNION ALL
SELECT '06/02/2011' AS DateOfBirth, 'Matthew' AS CustomerName UNION ALL
SELECT '07/13/2010' AS DateOfBirth, 'Rachel' AS CustomerName UNION ALL
SELECT '05/01/2011' AS DateOfBirth, 'Molly' AS CustomerName UNION ALL
SELECT '07/13/2010' AS DateOfBirth, 'Alex' AS CustomerName UNION ALL
SELECT '08/01/2009' AS DateOfBirth, 'John' AS CustomerName UNION ALL
SELECT '07/13/2010' AS DateOfBirth, 'Ann' AS CustomerName UNION ALL
SELECT '05/01/2011' AS DateOfBirth, 'Jay' AS CustomerName
) 
--By Month

--SELECT DATENAME(month, DateOfBirth)+DATENAME(year, dateofBirth), COUNT(*)
--FROM DummyTable
--GROUP BY DATENAME(month, DateOfBirth)+DATENAME(year, dateofBirth)


--BY Quarter

--SELECT CAST(DATEPART(QUARTER, DateOfBirth) AS Varchar)+' quarter '+DATENAME(year, dateofBirth), COUNT(*)
--FROM DummyTable
--GROUP BY CAST(DATEPART(QUARTER, DateOfBirth) AS Varchar)+' quarter '+DATENAME(year, dateofBirth)
1 голос
/ 15 июня 2011

Хотелось бы что-нибудь по этому адресу? Хитрость заключается в том, чтобы использовать и злоупотреблять функцией CONVERT , чтобы ваши периоды времени правильно объединялись, а затем использовать DENSE_RANK , чтобы уменьшить ее до монотонно увеличивающейся последовательности.

WITH DUMMY_DATA AS
(
-- use a convert with a type of 112 to coerce dates to
-- YYYY-MM format and truncate days
-- Be creative, use to generate whatever bands you desire
SELECT CONVERT(char(7), '2011-06-01', 112) AS period, 'stuff' AS junk
UNION ALL SELECT CONVERT(char(7), '2011-05-01', 112) AS period, 'more stuf' AS junk
UNION ALL SELECT CONVERT(char(7), '2011-05-01', 112) AS period, 'more stuf1' AS junk
UNION ALL SELECT CONVERT(char(7), '2011-05-01', 112) AS period, 'more stuf2' AS junk
UNION ALL SELECT CONVERT(char(7), '2011-05-01', 112) AS period, 'more stuf3' AS junk
UNION ALL SELECT CONVERT(char(7), '2011-05-01', 112) AS period, 'more stu4f' AS junk
UNION ALL SELECT CONVERT(char(7), '2011-05-01', 112) AS period, 'more stuf5' AS junk
UNION ALL SELECT CONVERT(char(7), '2011-05-01', 112) AS period, 'more stuf7' AS junk
UNION ALL SELECT CONVERT(char(7), '2011-05-01', 112) AS period, 'more stuf8' AS junk
UNION ALL SELECT CONVERT(char(7), '2011-05-01', 112) AS period, 'more stuf9' AS junk
UNION ALL SELECT CONVERT(char(7), '2011-05-01', 112) AS period, 'more stuf0' AS junk
)
, BANDS AS
(
-- Using our data, create bands in case you want to look
-- at groupings 
SELECT
    D.*
,   DENSE_RANK() OVER (ORDER BY D.period ASC) AS banding
FROM
    DUMMY_DATA D
)
, ROLLUPS AS
(
-- ROll up based on our banding
SELECT
    B.period
,   B.banding
,   COUNT(1) AS row_count
FROM
    BANDS B
GROUP BY
    B.period
,   B.banding

) SELECT * FROM ROLLUPS R

Используя вышеизложенное, я получаю вывод как

[period]   [band]  [row_count]
2011-05    1       10
2011-06    2       1
...