Microsoft SQL SERVER: Строки группы по 30 минут в соответствии с первой строкой (строки могут иметь разные дни и время) - PullRequest
1 голос
/ 13 марта 2020

У меня есть таблица транзакций с разными столбцами, для примера я оставляю под сомнение только связанные.

Моя таблица: транзакция

id  TransactionTime             idClient 
---------------------------------------------
1   2019-05-29 09:37:30.000     1531201523215
1   2019-05-29 09:37:30.000     1531201523215
2   2019-05-29 10:20:06.000     1531201523215
3   2019-05-29 10:45:19.000     1531201523215
4   2019-05-29 10:50:19.000     1531201523215
5   2019-05-29 10:51:43.000     1531201523215
6   2019-05-29 10:57:36.000     1531201523215
6   2019-05-29 10:57:36.000     1531201523215
7   2019-05-30 10:07:14.000     1531201523215
8   2019-05-30 10:37:12.000     1531201523215
9   2019-05-30 10:38:11.000     1531201523215
10  2019-05-30 10:46:17.000     1531201523215

Чего я хочу достичь Группировать строки в пределах 30 минут друг от друга, желаемый результат будет

id  TransactionTime             idClient            Count
----------------------------------------------------------
1   2019-05-29 09:37:30.000     1531201523215       2  
2   2019-05-29 10:20:06.000     1531201523215       2
4   2019-05-29 10:50:19.000     1531201523215       4
7   2019-05-30 10:07:14.000     1531201523215       2      
9   2019-05-30 10:38:11.000     1531201523215       2

Я пытался использовать:

SELECT ROW_NUMBER() OVER (
        PARTITION BY tl.idClient
        ,(dateadd(minute, (datediff(second, 0, tl.TransactionTime) / 60 / 30) * 30, 0)) ORDER BY tl.idClient
            ,tl.TransactionTime
        ) AS filter_row

Но я не смог достичь того, что хотел ... Был застрял на 4 дня сейчас ... Пожалуйста, помогите.

1 Ответ

2 голосов
/ 13 марта 2020

Для этого вам нужен рекурсивный запрос. Идея состоит в том, чтобы начать с первой записи за id_client (согласно transaction_time), а затем пройти группу по возрастанию transaction_time.

with 
    tab as (
        select t.*, row_number() over(partition by id_client order by transaction_time) rn
        from mytable t
    ),
    cte as (
        select id, id_client, rn, transaction_time from tab where rn = 1
        union all
        select 
            t.id,
            t.id_client,
            t.rn,
            case when t.transaction_time > dateadd(minute, 30, c.transaction_time)
                then t.transaction_time
                else c.transaction_time
            end
        from cte c
        inner join tab t on t.id_client = c.id_client and t.rn = c.rn + 1

    )
select min(id) id, transaction_time, id_client, count(*) cnt
from cte 
group by id_client, transaction_time
order by id_client, transaction_time

Демонстрация в БД Скрипка :

id | transaction_time        | id_client     | cnt
-: | :---------------------- | :------------ | --:
 1 | 2019-05-29 09:37:30.000 | 1531201523215 |   2
 2 | 2019-05-29 10:20:06.000 | 1531201523215 |   2
 4 | 2019-05-29 10:50:19.000 | 1531201523215 |   4
 7 | 2019-05-30 10:07:14.000 | 1531201523215 |   2
 9 | 2019-05-30 10:38:11.000 | 1531201523215 |   2
...