SQL - подсчет и суммирование (в диапазонах) количества экземпляров данной транзакции - PullRequest
1 голос
/ 25 января 2010

У меня есть таблица событий, которая содержит одну строку для каждого действия пользователя. Пользователь совершает действие несколько раз в день. Это выглядит так:

Date      Username
------    --------
1/1/9     User1
1/1/9     User1
1/1/9     User2
1/2/9     User1
1/2/9     User3
1/3/9     User1
1/3/9     User1
1/3/9     User1
1/3/9     User2
1/3/9     User3
1/4/9     User1
1/5/9     User1
1/6/9     User1
1/7/9     User1

Для каждого дня в диапазоне я хотел бы показать количество людей, которые предприняли действие несколько раз - скажем, от 2 до 5 раз, от 6 до 10 раз и более 10 раз. Тем не менее, я только думаю повторить действие в другой день, чтобы считать его еще одним экземпляром этого действия. Например, если пользователь делал это 3 раза в первый день, а затем снова любое количество раз на следующий день, я вижу, что пользователь выполнил действие 2 раза и, следовательно, должно быть от 2 до 5 раз колонка.

Набор результатов, соответствующий приведенным выше образцам данных, будет:

        #_of_people       #_of_people       #_of_people       
        who_did_action    who_did_action    who_did_action        
Date    2to5_times        6to10_times       more_than_10      Total
-----   --------------    --------------    --------------    -----
1/1/9   0                 0                 0                 0
1/2/9   1                 0                 0                 1
1/3/9   3                 0                 0                 3   
...    
1/7/9   0                 1                 0                 1        

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

  • Строка 1/1/9 - это все нули, поскольку это первый день, а все действия считаются первыми.
  • Строка 1/2/9 равна 1, 0, 0, 1, потому что только Пользователь1 повторил - это первый раз Пользователя 3.
  • Строка 1/3/9 - 3, 0, 0, 3, потому что Пользователь1 повторил дважды, Пользователь2 повторил один раз, а Пользователь3 также повторил один раз.
  • Строка 1/7/9 равна 0, 1, 0, 1, потому что пользователь 1 повторил 6 раз.

Ответы [ 2 ]

1 голос
/ 25 января 2010

Лучшее, что я мог придумать, не проверено:

DECLARE @username VARCHAR(40)
DECLARE @date DATETIME
DECLARE @counter INT
    SET @counter = 1

WITH occur AS (
     SELECT DISTINCT
            CONVERT(VARCHAR(10), o.date, 101) AS dt,
            o.username
       FROM OCCURRENCES o
   ORDER BY o.username, dt),
     occur_rank AS (
     SELECT x.dt,
            @username = x.username,
            @date = CAST(x.dt AS DATETIME),
            CASE WHEN @username = x.username AND @date + 1 = x.date THEN @counter = @counter + 1 ELSE @counter = 1 END AS rank
       FROM occur x
   ORDER BY x.username, x.dt)
  SELECT or.dt,
         SUM(CASE WHEN or.rank BETWEEN 2 AND 5 THEN 1 ELSE 0 END) AS 2_to_5,
         SUM(CASE WHEN or.rank BETWEEN 6 AND 10 THEN 1 ELSE 0 END) AS 6_to_10
    FROM occur_rank or
GROUP BY or.dt

Если вы можете восстановить нумерацию в промежутке между датами, остальное легко. Но ни одна из функций ранжирования SQL Server не поддерживает это . Так что оставляет вручную увеличивая переменную.

Первый CTE, occur просто возвращает список имен пользователей, связанных с датами. Второй CTE основывается на нем, добавляя ранжирование для конечного результата в разворот.

0 голосов
/ 16 ноября 2016

Я использовал производную таблицу с коррелированным подзапросом.

Соответствующий подзапрос приводит к столбцу ActionCount, который подсчитывает количество различных дат до и включая дату этой строки для имени пользователя этой строки.

В полученной производной таблице перечислены все Дата, Имя пользователя и ActionCount.

Внешний запрос затем группирует результаты по дате, подсчитывая количество ActionCounts от 2 до 5, от 6 до 10, больше 10 и, для итога, больше 1 (ActionCount, равное 1, не является 'повтор').

select
    [Date],
    sum(case when [ActionCount] between 2 and 5 then 1 else 0 end) [#_of_people_who_did_action_2to5_times],
    sum(case when [ActionCount] between 6 and 10 then 1 else 0 end) [#_of_people_who_did_action_6to10_times],
    sum(case when [ActionCount] > 10 then 1 else 0 end) [#_of_people_who_did_action_more_than_10],
    sum(case when [ActionCount] > 1 then 1 else 0 end) [Total]
from (
    select distinct
        dt.[Date],
        dt.[Username],
        (select count(distinct [Date]) from OCCURRENCES cd where cd.[Username] = dt.[Username] and cd.[Date] <= dt.[Date]) [ActionCount]
    from OCCURRENCES dt
) a
group by [Date]
...