SQL: Как выбрать ТОЛЬКО заказы, которые выполняются каждые три недели?

#sql #sql-server #tsql

#sql #sql-сервер #tsql

Вопрос:

У меня есть таблица заказов, в которой заказы размещаются каждый четверг. Соответственно, с каждым заказом связано fiscal_week_number от 1 до 52.

Каждый заказ группируется в пакеты, где один заказ может содержать несколько транзакций, каждая из которых оплачивается за отдельную неделю. Например, order_number 0001 выставил счет за fiscal_week_numbers 4, 5, 6, 7 и имел transaction_numbers 100000001, 100000002, 100000003, 100000004. Предположим, что transaction_numbers не являются последовательными и случайными.

Некоторые заказы выставляются каждую неделю, некоторые — каждые две недели, некоторые — каждые 3 недели и т.д. Как я могу запросить таблицу, чтобы показывать только заказы, которые выставляются каждые X недель?

Например, я хотел бы узнать, сколько заказов (то есть различных order_ids ) выставляется каждые 6 недель, но я не могу определить SQL.

Например, скажем, я хотел захватить только заказы, которые выполняются каждые три недели, из следующего набора данных. Я ожидал бы получить только заказ 00003 . На самом деле не имеет значения, есть ли все данные заказа или только идентификатор.

 |00003   |319229           |20            |
|00003   |319230           |23            |
|00003   |238678           |26            |
|00003   |319231           |29            |
|00003   |190659           |32            |
  
  -------- ----------------- -------------- 
|order_id|transactionnumber|fiscal_week_no|
 -------- ----------------- -------------- 
|00001   |278100           |1             |
|00001   |278101           |2             |
|00001   |278102           |3             |
|00001   |278103           |4             |
|00001   |278104           |5             |
|00002   |319224           |10            |
|00002   |319225           |12            |
|00002   |319226           |14            |
|00002   |319227           |16            |
|00002   |319228           |18            |
|00003   |319229           |20            |
|00003   |319230           |23            |
|00003   |238678           |26            |
|00003   |319231           |29            |
|00003   |190659           |32            |
|00004   |319232           |26            |
|00004   |190660           |30            |
|00004   |190661           |34            |
|00004   |190662           |38            |
|00004   |319233           |42            |
|00005   |190663           |40            |
|00005   |319234           |45            |
|00005   |190664           |50            |
|00005   |190665           |3             |
|00005   |190666           |8             |
|00006   |319235           |10            |
|00006   |190667           |16            |
|00006   |190668           |22            |
|00006   |319236           |28            |
|00006   |190669           |34            |
|00007   |319237           |20            |
|00007   |190670           |28            |
|00007   |190671           |36            |
|00007   |319238           |44            |
|00007   |190672           |52            |
|00007   |190673           |8             |
 -------- ----------------- -------------- 

  

Комментарии:

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

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

3. @GMB добавил еще несколько пояснений.

4. Существует ли когда-либо 53-я финансовая неделя? (52 * 7 = 364, что приводит к дополнительной неделе каждые несколько лет. И високосные дни также влияют на сочетание.) Могут ли быть данные более чем за один год?

5. @HABO да, есть данные более чем за один год, и, к моему удивлению, во многих заказах финансовая неделя составляет 53.

Ответ №1:

Исходя из вашего описания, заказы выставляются каждые три недели, если fiscal_week_no столбец всегда одинаков по модулю 3. Итак, один из методов:

 select order_id
from t
group by order_id
having min(fiscal_week_no % 3) = max(fiscal_week_no % 3);
  

Обратите внимание, что это не гарантирует, что они выставляются каждые три недели (мы могли бы добавить дополнительную проверку для этого. Но это будут заказы в одном и том же платежном цикле.

Комментарии:

1. Это действительно элегантное решение… Как бы вы добавили эту проверку для последовательных циклов выставления счетов?

2. Заказ, который отправляется в течение финансовых недель 52 и 3 завершается неудачно: 52 % 3 = 1 , 3 % 3 = 0 . Поскольку 52 количество пересечений не превышает 3 количества лет, это проблема. (Ожидание подтверждения OP, что могут существовать данные за несколько лет. Или 53 недели время от времени.)

3. @qotsa42 . . . Для последовательных циклов выставления счетов я бы просто использовал count(*) = max(fiscal_week_no) - min(fiscal_week_no) .

Ответ №2:

Я думаю, что этот код тоже может быть полезен. Это вернет order_id для любого количества транзакций, установленного в переменной @bill_freq. Я использовал составленные данные.

 declare @bill_freq          int=2;

;with rn_cte(order_id, transactionnumber, fiscal_week_no, wk_rn) as (
    select *, row_number() over (partition by order_id order by order_id, fiscal_week_no) wk_rn
    from (values ('00001', 278100, 1),
                 ('00001', 278101, 2),
                 ('00002', 278102, 3),
                 ('00002', 278103, 4),
                 ('00003', 278104, 5),
                 ('00004', 278105, 7),
                 ('00004', 278106, 9)) v(order_id, transactionnumber, fiscal_week_no))
select order_id
from rn_cte
group by order_id
having max(wk_rn)=@bill_freq;
  

Результаты

 order_id
00001
00002
00004