Могу ли я установить рекурсивный CTE с помощью предложения WHERE в VIEW? - PullRequest
1 голос
/ 27 мая 2020

Я хочу сделать этот запрос представлением, которое генерирует рекурсивное CTE дат на основе любого желаемого временного интервала. Прямо сейчас я установил дату начала как 30.12.2019 и дату закрытия рекурсии как 1/4/2020 для целей этого примера. Я знаю, что у меня нет возможности устанавливать переменные в представлениях, однако мне интересно, есть ли способ сделать это косвенно. Есть ли способ сделать дату начала и дату окончания генерального разрыва зависимыми от предложения where?

Вот запрос

WITH Dates AS (
    SELECT [GenGapDate] = CONVERT(DATETIME,'12/30/2019') -- // this is the starting date
    UNION ALL 
    SELECT [GenGapDate] = DATEADD(DAY, 1, [GenGapDate])
    FROM Dates
    WHERE GenGapDate < '1/4/2020'
),
StoreXJoinDate as (
    select  d.[GenGapDate],
            s.Store,
            s.OpenDate,
            s.CloseDate
    from Dates  as d
    cross join #Stores s
),
POSQtySum as (
    select 
            p.SaleDate,
            p.Store,
         sum(p.Qty)  as TotQty
    from #POS p
    group by p.SaleDate, p.Store
),
StoreQty as (
    select  distinct 
            x.GenGapDate,
            x.Store,
            p.Store as PosStore,
            x.OpenDate,
            x.CloseDate,
            isnull(p.TotQty,0) as TotQty
    from StoreXJoinDate x
    full outer join POSQtySum p on  p.Store = x.Store
                                and p.SaleDate = x.GenGapDate
),
BaseResultSet as (
    select  GenGapDate,
            Store,
            OpenDate,
            CloseDate,
            TotQty,
            1 as StoreIsMissing
    from StoreQty
    where TotQty = 0
    and (
            CloseDate is null 
            or (CloseDate >= GenGapDate)
    )
    and OpenDate is not null
    and GenGapDate >= OpenDate
    union
    select  GenGapDate,
   Store,
   OpenDate,
   CloseDate,
   TotQty,
   NULL as StoreIsMissing
    from StoreQty
    where TotQty > 0
)
select  GenGapDate,
        Store,
        OpenDate,
        CloseDate,
        TotQty,
        StoreIsMissing
from BaseResultSet
order by GenGapDate desc, Store asc;

Вот сценарий построения для генерации данных для работы с запросом.

create table #Stores  -- drop table #Stores
(Store int,
 OpenDate date,
 CloseDate date
 );

 create table #ProdCat -- drop table #ProdCat
 (ProdCatId int,
  ProdCatName varchar(10)
  );

 create table #POS -- drop table #POS
 (SaleDate date,
  Store int,
  ProdCatId int,
  Qty int
  );

-- Store inserts
insert into #Stores
(Store,OpenDate,CloseDate)
values
(123,'2019-12-31',NULL);

insert into #Stores
(Store,OpenDate,CloseDate)
values
(124,'1995-01-01',NULL);

insert into #Stores
(Store,OpenDate,CloseDate)
values
(125,'2000-01-01','2020-01-03');

-- ProdCat inserts
insert into #ProdCat
(ProdCatId,ProdCatName)
values
(1,'Produce');

insert into #ProdCat
(ProdCatId,ProdCatName)
values
(2,'Diary');

-- POS inserts
insert into #POS
(SaleDate,ProdCatId,Store,Qty)
values
('2019-12-30',1,124,420);

insert into #POS
(SaleDate,ProdCatId,Store,Qty)
values
('2019-12-30',2,124,180);

-- --

insert into #POS
(SaleDate,ProdCatId,Store,Qty)
values
('2020-01-02',1,123,10);

insert into #POS
(SaleDate,ProdCatId,Store,Qty)
values
('2020-01-02',2,123,10);

insert into #POS
(SaleDate,ProdCatId,Store,Qty)
values
('2020-01-02',1,124,500);

insert into #POS
(SaleDate,ProdCatId,Store,Qty)
values
('2020-01-02',2,124,200);

insert into #POS
(SaleDate,ProdCatId,Store,Qty)
values
('2020-01-02',1,125,50);

insert into #POS
(SaleDate,ProdCatId,Store,Qty)
values
('2020-01-02',2,125,0);

-- --

insert into #POS
(SaleDate,ProdCatId,Store,Qty)
values
('2020-01-03',1,123,12);

insert into #POS
(SaleDate,ProdCatId,Store,Qty)
values
('2020-01-03',2,123,15);

insert into #POS
(SaleDate,ProdCatId,Store,Qty)
values
('2020-01-03',1,124,510);

insert into #POS
(SaleDate,ProdCatId,Store,Qty)
values
('2020-01-03',2,124,195);

-- --

insert into #POS
(SaleDate,ProdCatId,Store,Qty)
values
('2020-01-04',1,123,6);

insert into #POS
(SaleDate,ProdCatId,Store,Qty)
values
('2020-01-04',2,123,10);

insert into #POS
(SaleDate,ProdCatId,Store,Qty)
values
('2020-01-04',1,124,610);

insert into #POS
(SaleDate,ProdCatId,Store,Qty)
values
('2020-01-04',2,124,220);

Ответы [ 2 ]

1 голос
/ 27 мая 2020

В зависимости от того, как вы хотите его использовать, вы можете превратить все это в табличную функцию .

create function MissingStores (@startDate date, @endDate date)
returns table
as
return 
  (
        WITH Dates AS (
            SELECT [GenGapDate] = @startDate -- // this is the starting date
            UNION ALL 
            SELECT [GenGapDate] = DATEADD(DAY, 1, [GenGapDate])
            FROM Dates
            WHERE GenGapDate < @endDate
        ),
        StoreXJoinDate as (
       ... <The rest of your query....>
  );

Это фактически SQL серверная реализация параметризованных представлений. Отсюда вы рассматриваете функцию как таблицу, но с параметрами. Обратите внимание, что ORDER BY находится вне функции. Функции не поддерживают предложения ORDER BY.

select *
from MissingStores ('20191230', '20200104')
order by GenGapDate desc, Store asc;

Результаты (простите, пожалуйста, формат даты Rextester):

|    |     GenGapDate      | Store |      OpenDate       |      CloseDate      | TotQty | StoreIsMissing |
+----+---------------------+-------+---------------------+---------------------+--------+----------------+
|  1 | 04.01.2020 00:00:00 |   123 | 31.12.2019 00:00:00 | NULL                |     16 | NULL           |
|  2 | 04.01.2020 00:00:00 |   124 | 01.01.1995 00:00:00 | NULL                |    830 | NULL           |
|  3 | 03.01.2020 00:00:00 |   123 | 31.12.2019 00:00:00 | NULL                |     27 | NULL           |
|  4 | 03.01.2020 00:00:00 |   124 | 01.01.1995 00:00:00 | NULL                |    705 | NULL           |
|  5 | 03.01.2020 00:00:00 |   125 | 01.01.2000 00:00:00 | 03.01.2020 00:00:00 |      0 | 1              |
|  6 | 02.01.2020 00:00:00 |   123 | 31.12.2019 00:00:00 | NULL                |     20 | NULL           |
|  7 | 02.01.2020 00:00:00 |   124 | 01.01.1995 00:00:00 | NULL                |    700 | NULL           |
|  8 | 02.01.2020 00:00:00 |   125 | 01.01.2000 00:00:00 | 03.01.2020 00:00:00 |     50 | NULL           |
|  9 | 01.01.2020 00:00:00 |   123 | 31.12.2019 00:00:00 | NULL                |      0 | 1              |
| 10 | 01.01.2020 00:00:00 |   124 | 01.01.1995 00:00:00 | NULL                |      0 | 1              |
| 11 | 01.01.2020 00:00:00 |   125 | 01.01.2000 00:00:00 | 03.01.2020 00:00:00 |      0 | 1              |
| 12 | 31.12.2019 00:00:00 |   123 | 31.12.2019 00:00:00 | NULL                |      0 | 1              |
| 13 | 31.12.2019 00:00:00 |   124 | 01.01.1995 00:00:00 | NULL                |      0 | 1              |
| 14 | 31.12.2019 00:00:00 |   125 | 01.01.2000 00:00:00 | 03.01.2020 00:00:00 |      0 | 1              |
| 15 | 30.12.2019 00:00:00 |   124 | 01.01.1995 00:00:00 | NULL                |    600 | NULL           |
| 16 | 30.12.2019 00:00:00 |   125 | 01.01.2000 00:00:00 | 03.01.2020 00:00:00 |      0 | 1              |
+----+---------------------+-------+---------------------+---------------------+--------+----------------+

Rextester Demo

1 голос
/ 27 мая 2020

Вы можете сделать что-то вроде:

WITH Dates AS (
            SELECT OpenDate From Stores WHERE Store=124 -- // this is the starting date
            UNION ALL 
            SELECT [GenGapDate] = DATEADD(DAY, 1, [GenGapDate])
            FROM Dates
            WHERE GenGapDate < (SELECT max(EndDate) From Stores WHERE store=124)
        ),

Я не уверен, что это то, что вы ищете, поскольку вы не указали, откуда берутся ваши переменные даты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...