Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Выборка периодов с разбивкой на даты  [new]
kjt
Member

Откуда:
Сообщений: 8
Доброго времени суток, коллеги!
Есть таблица в которой хранится прайс лист с наименованиями товара и периодом действия:
select name, dateFrom, dateTo from TABLE


Товар 1 2019-01-17 00:00:00.000 2019-01-20 00:00:00.000
Товар 2 2019-01-18 00:00:00.000 2019-01-19 00:00:00.000
Товар 3 2019-01-29 00:00:00.000 2019-01-30 00:00:00.000

Нужно как то периоды разбить на даты и получить результат в таком виде:
Товар 1 2019-01-17 00:00:00.000
Товар 1 2019-01-18 00:00:00.000
Товар 1 2019-01-19 00:00:00.000
Товар 1 2019-01-20 00:00:00.000
Товар 2 2019-01-18 00:00:00.000
Товар 2 2019-01-19 00:00:00.000
Товар 3 2019-01-29 00:00:00.000
Товар 3 2019-01-30 00:00:00.000

Видел много решений по разбивке периодов, но не могу понять как эти функции интегрировать в запрос.
Подскажите красивое решение.
5 дек 19, 06:33    [22032696]     Ответить | Цитировать Сообщить модератору
 Re: Выборка периодов с разбивкой на даты  [new]
crutchmaster
Member

Откуда: оттуда.
Сообщений: 1543
kjt,
Пока всё равно все спецы спят, так что напишу я.

В общем случае надо таблицу (сгенерированную) с датами, тупо 1 день за запись. Потом берешь и связываешь:
select a.name, b.date from a,b where b.date between a.datefrom and a.dateto

Хотя в mssql может быть есть для такого специальный костыль.
5 дек 19, 06:51    [22032699]     Ответить | Цитировать Сообщить модератору
 Re: Выборка периодов с разбивкой на даты  [new]
crutchmaster
Member

Откуда: оттуда.
Сообщений: 1543
kjt,

https://www.sqlshack.com/how-to-generate-random-sql-server-test-data-using-t-sql/
А сам генератор дат делается через рекурсивный запрос т.е. через жопу. Но тут всё делается так. Это нормально.

with seq
    as(
       select 1 id
        union  all
        select id + 1
        from seq
        where 
          id < 1000
      )
   
 select * from seq OPTION(MAXRECURSION 0)

Дату заместо id сделай сам, у меня нет mssql под рукой.

Сообщение было отредактировано: 5 дек 19, 07:25
5 дек 19, 07:22    [22032703]     Ответить | Цитировать Сообщить модератору
 Re: Выборка периодов с разбивкой на даты  [new]
Massa52
Member

Откуда:
Сообщений: 379
kjt,

DECLARE
  @Begin date = '20190101',
  @End   date = '20190131';

DECLARE @t AS TABLE (tovar NVARCHAR(10), bg  DATETIME, en  DATETIME)
INSERT INTO @t VALUES 
(N'Товар 1', '2019-01-17 00:00:00.000', '2019-01-20 00:00:00.000'),
(N'Товар 2', '2019-01-18 00:00:00.000', '2019-01-19 00:00:00.000'),
(N'Товар 3', '2019-01-29 00:00:00.000', '2019-01-30 00:00:00.000')
SELECT * FROM @t t  

;WITH x AS
(
	SELECT 
		ROW_NUMBER() OVER (ORDER BY 1/0) AS num
	FROM master..spt_values
),
d AS 
(SELECT 
	CAST(DATEADD(day, x.num - 1, @Begin) as DATE) date
FROM x
WHERE CAST(DATEADD(day,x.num,@Begin) as DATE) <= @End
)
SELECT * FROM @t t CROSS APPLY d 
WHERE d.date >= t.bg AND d.date <= t.en 
5 дек 19, 07:43    [22032706]     Ответить | Цитировать Сообщить модератору
 Re: Выборка периодов с разбивкой на даты  [new]
kjt
Member

Откуда:
Сообщений: 8
Massa52,

Благодарю!
5 дек 19, 07:53    [22032707]     Ответить | Цитировать Сообщить модератору
 Re: Выборка периодов с разбивкой на даты  [new]
Akina
Member

Откуда: Зеленоград, Москва, Россия
Сообщений: 20536
WITH 
cte AS ( SELECT name, dateFrom [date], dateTo
         FROM [TABLE]
         /* WHERE dateFrom <= dateTo */
     UNION ALL
         SELECT name, DATEADD(day, 1, [date]), dateTo
         FROM cte
         WHERE [date] < dateTo
)
SELECT name, [date]
FROM cte
ORDER BY 1,2

fiddle
5 дек 19, 09:08    [22032747]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить