#sql #sql-server #join #resultset #self-join
Вопрос:
У вас есть набор данных, как показано ниже, и вы хотели бы знать различные способы решения вопроса : какой процент заказов был в течение 20 минут друг от друга?
Идентификатор клиента | Заказ_# | Дата заказа |
---|---|---|
123 | 000112 | 12/25/2011 10:30 |
123 | 000113 | 12/25/2011 10:35 |
123 | 000114 | 12/25/2011 10:45 |
123 | 000115 | 12/25/2011 10:55 |
456 | 000113 | 12/25/2011 10:35 |
456 | 000113 | 1/25/2011 10:30 |
789 | 000117 | 9/25/2011 2:00 |
Результирующий набор должен выглядеть следующим образом:
3/7 = 0.42%
Мой подход состоял в том, чтобы сначала выполнить самостоятельное объединение с таблицей, чтобы получить количество строк, которые попадают в 20%, но изо всех сил пытаются удалить повторяющиеся строки.
В любом случае, с нетерпением жду некоторых хитрых ответов.
Спасибо.
Комментарии:
1. Отредактируйте свой вопрос и покажите результаты, которые вы хотите. Также пометьте базу данных, которую вы используете.
2. Спасибо, Гордон, добавлен тег для SQL Server
3. Я насчитал 4, которые находятся в течение 20 минут после другого заказа, а не 3.
Ответ №1:
Вы можете использовать lead()
и lag()
:
select avg( case when prev_order_date > order_date - interval '20 minute' or
next_order_date < order_date interval '20 minute'
then 1.0 else 0
end) as ratio_within_20_minutes
from (select t.*,
lag(order_date) over (partition by customer_id order by order_date) as prev_order_date,
lead(order_date) over (partition by customer_id order by order_date) as next_order_date
from t
) t;
Обратите внимание, что функции даты/времени сильно различаются в разных базах данных. Для сравнения используется стандартный синтаксис SQL. Точный синтаксис, вероятно, варьируется в зависимости от вашей базы данных.
Если вы хотите, чтобы это было для каждого клиента, добавьте group by customer_id
в запрос и customer_id
в select
.
Редактировать:
В SQL Server это было бы:
select avg( case when prev_order_date > dateadd(minute, -20, order_date) or
next_order_date < dateadd(minute, 20, order_date)
then 1.0 else 0
end) as ratio_within_20_minutes
from (select t.*,
lag(order_date) over (partition by customer_id order by order_date) as prev_order_date,
lead(order_date) over (partition by customer_id order by order_date) as next_order_date
from t
) t;
Комментарии:
1. Спасибо. Будет ли приведенный ниже измененный запрос также давать тот же результат? ВЫБЕРИТЕ СУММА(TIMEDIFF)/КОНВЕРТИРОВАТЬ(десятичное число(4,2),КОЛИЧЕСТВО(ИДЕНТИФИКАТОР ЗАКАЗА)) ОТ ( ВЫБЕРИТЕ СЛУЧАЙ,КОГДА ДАТА(МИНУТА,дата предварительного заказа, дата следующего заказа) [SAMPLE_ORDER2] t) t )A