2016-06-09 2 views
0

У меня есть таблица с значениями пользователя и даты. Для каждого пользователя может быть несколько значений даты. В приведенном ниже скрипте я вставляю столбцы fromPrevious и fromFirst во время выбора, для каждого пользователя на основе другого ответа, который я нашел в stackoverflow.групповые серии, основанные на ограниченных периодах времени с SQL Server

SELECT 
a.user as 'user' 
,a.date as 'date' 
,ISNULL(DATEDIFF(day,b.date,a.date),0) as 'sincePrevious' 
,datediff(day, min(a.date) over (partition by a.user), a.date) as 'sinceFirst' 
FROM 
(select *,ROW_NUMBER() OVER(PARTITION BY user ORDER BY date) as Rank from HUT_regels) as a 
LEFT JOIN 
(select *,ROW_NUMBER() OVER(PARTITION BY user ORDER BY date) as Rank from HUT_regels) as b 
ON a.user = b.user AND a.Rank = b.Rank + 1 
ORDER by 'user', 'date' 

То, что я хочу сделать, это вставить другой столбец аналогичным образом (во время выбора), который добавляет уникальный идентификатор группы на основе значения пользователя, и разница во времени между двумя рядами. В этом примере я добавил несколько идентификаторов групп. Когда разница между датами между двумя последовательными датами для одного и того же пользователя больше 50 дней (в этом примере), это следует рассматривать как новую «последовательность» вступлений. groupIDs 2, 3 и 4 отражают это.

user  date  sincePrevious sinceFirst groupId 
100000029 25-05-2012 0    0   1 
100002161 08-01-2012 0    0   2 
100002161 04-02-2012 27    27   2 
100002161 15-02-2012 11    38   2 
100002161 28-03-2012 42    80   2 
100002161 23-05-2012 56    136   3 
100002161 11-07-2012 49    185   3 
100002161 29-08-2012 49    234   3 
100002161 24-10-2012 56    290   4 
100002161 21-11-2012 28    318   4 
100005242 07-05-2013 0    0   5 
100005242 10-05-2013 3    3   5 
100005242 14-05-2013 4    7   5 
100005242 17-05-2013 3    10   5 
100005242 21-05-2013 4    14   5 
100005242 24-05-2013 3    17   5 
100005242 28-05-2013 4    21   5 
100005242 07-06-2013 10    31   5 
... 

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

Я знаю, что это возможно с помощью CTE, но хотелось бы найти решение, подобное способу с момента появления и с момента создания First.

My usecase - это SQL Server, но более универсальное решение (я упоминаю MySQL, но PostgreSQL, к примеру, также было бы неплохо) также могло бы помочь другим.

+0

Нет универсального решения, когда оно включает в себя функции CTE или Analytical, поскольку RDBM обрабатывает его по-разному, а некоторые даже не поддерживают его (например, аналитические функции в mysql не являются) –

+0

Я знаю, что я имел в виду, как @ Gordon- Linoff сказал больше ANSI-подобного решения. –

ответ

0

Во-первых, вы должны использовать lag() и min(), чтобы получить значения:

select r.*, 
     datediff(day, lag(date) over (partition by user order by date), date) as sincePrevious, 
     datediff(day, min(date) over (partition by user), date) as sinceFirst 
from HUT_regels r; 

Чтобы добавить GroupId, вам просто нужно подзапрос и условной агрегации:

select r.*, 
     sum(case when sincePrevious < 0 then 0 else 1 end) over 
      (partition by user order by date) as groupId 
from (select r.*, 
      datediff(day, lag(date) over (partition by user order by date), date) as sincePrevious, 
      datediff(day, min(date) over (partition by user), date) as sinceFirst 
     from HUT_regels r 
    ) r; 

Это все стандартные ANSI функциональность. Однако он не был полностью введен в SQL Server до версии 2012. В более ранних версиях вместо этого вы можете использовать apply.

+0

Это не тот ответ, который я искал. Со вторым блоком кода groupId увеличивается на одну строку (при условии правильно отсортированного вывода) и сбрасывается с нового пользователя. –

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