Как извлечь даты в диапазоне? - PullRequest
1 голос
/ 16 апреля 2020

У меня есть таблица (SQL Server 2017), содержащая данные в диапазоне дат.

+---------+----------+------------+---------------+-------------+
| good_id | store_id | promo_name | date_id_begin | date_id_end |
+---------+----------+------------+---------------+-------------+
| 1122    | 42       | promo_1    | 2020-02-01    | 2020-02-05  |
+---------+----------+------------+---------------+-------------+
| 2244    | 41       | promo_2    | 2020-03-01    | 2020-03-03  |
+---------+----------+------------+---------------+-------------+

Мне нужно получить эти данные по дням в течение периода.

+---------+----------+------------+---------------+
| good_id | store_id | promo_name | date_id_begin |
+---------+----------+------------+---------------+
| 1122    | 42       | promo_1    | 2020-02-01    |
+---------+----------+------------+---------------+
| 1122    | 42       | promo_1    | 2020-02-02    |
+---------+----------+------------+---------------+
| 1122    | 42       | promo_1    | 2020-02-03    |
+---------+----------+------------+---------------+
| 1122    | 42       | promo_1    | 2020-02-04    |
+---------+----------+------------+---------------+
| 1122    | 42       | promo_1    | 2020-02-05    |
+---------+----------+------------+---------------+
| 2244    | 41       | promo_2    | 2020-03-01    |
+---------+----------+------------+---------------+
| 2244    | 41       | promo_2    | 2020-03-02    |
+---------+----------+------------+---------------+
| 2244    | 41       | promo_2    | 2020-03-03    |
+---------+----------+------------+---------------+

Я могу извлечь даты из диапазона внутри l oop, но как я могу выбрать другую информацию (good_id, store_id, promo_name)?

Ответы [ 2 ]

1 голос
/ 16 апреля 2020

Если у вас нет календаря или таблицы подсчета, вы можете использовать специальную таблицу подсчета c.

Пример

Select A.[good_id]
      ,A.[store_id]
      ,A.[promo_name] 
      ,[Date] = B.D
 From  YourTable A
 Join  (
         Select Top (25000) D=DateAdd(DAY,Row_Number() Over (Order By (Select Null)),'1999-12-31') From  master..spt_values n1,master..spt_values n2
       ) B  on D between date_id_begin and date_id_end

Возвращает

good_id store_id    promo_name  Date
1122    42          promo_1     2020-02-01
1122    42          promo_1     2020-02-02
1122    42          promo_1     2020-02-03
1122    42          promo_1     2020-02-04
1122    42          promo_1     2020-02-05
2244    41          promo_2     2020-03-01
2244    41          promo_2     2020-03-02
2244    41          promo_2     2020-03-03
1 голос
/ 16 апреля 2020

Одним из вариантов является рекурсивный запрос:

with cte as (
    select good_id, store_id, promo_name, date_id_begin, date_id_end
    from mytable
    union all
    select good_id, store_id, promo_name, dateadd(day, 1, date_id_begin), date_id_end
    from cte 
    where date_id_begin < date_id_end
)
select good_id, store_id, promo_name, date_id_begin from cte

Если у вас есть диапазоны, которые охватывают более 100 дней, вам нужно добавить option(max_recursion 0) в конце запроса.

...