Sql представление, которое показывает, что последнее + создает строку для первого дня, если не присутствует в наборе данных - PullRequest
0 голосов
/ 06 июня 2018

У меня есть следующие данные:

Date Store Product Price
d1   s1    p1      0
d1   s1    p2      0
d1   s2    p1      0
d2   s1    p1      0
...

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

SELECT * FROM TableName WHERE date > DATEADD(day, -X, GETDATE())

Но мне также нужно убедиться, что у меня есть запись на все X дней для каждой пары магазин-продукт.Таким образом, если в сегодняшние X дней нет записи для определенной пары магазина и продукта, мне нужно найти последнюю цену для этой пары (если она существует), а затем скопировать эту цену в строку с датой = сегодня - X.Имеет ли это смысл?

Ответы [ 2 ]

0 голосов
/ 06 июня 2018

Если я понимаю вопрос так, как вижу его, то для этого примера данных

CREATE TABLE t1
    ([Date] DATE, [Store] varchar(2), [Product] varchar(2), [Price] int)
;

INSERT INTO t1
    ([Date], [Store], [Product], [Price])
VALUES
    ('20180525', 's1', 'p3', 0),
    ('20180601', 's1', 'p1', 0),
    ('20180602', 's1', 'p2', 0),
    ('20180603', 's2', 'p1', 0),
    ('20180604', 's1', 'p1', 0)
;

DECLARE @NumOfDays INT = 10

ОП хочет показать ('20180525', 's1', 'p3', 0) строку, как это было раньше DATEADD( DAY, -@NumOfDays, GETDATE()) дней назад

Поэтому попробуйте это решение

SELECT
     --T.Date
     [Date] = CAST(DATEADD( DAY, -@NumOfDays, GETDATE()) AS DATE)
    ,T.Store
    ,T.Product
    ,T.Price
FROM dbo.t1 T
INNER JOIN(
    SELECT Mxdate = MAX(T2.Date), T2.Store, T2.Product
    FROM dbo.t1 T2
    GROUP BY T2.Store, T2.Product
) MxDate ON MxDate.Product = T.Product AND MxDate.Store = T.Store
WHERE MxDate.Mxdate < DATEADD( DAY, -@NumOfDays, GETDATE())
UNION
SELECT
     T3.Date
    ,T3.Store
    ,T3.Product
    ,T3.Price
FROM dbo.t1 T3
WHERE T3.Date > DATEADD( DAY, -@NumOfDays, GETDATE())

Вывод

Date        Store   Product Price
2018-05-27  s1      p3      0       --this is the row before the daterange
2018-06-01  s1      p1      0
2018-06-02  s1      p2      0
2018-06-03  s2      p1      0
2018-06-04  s1      p1      0
0 голосов
/ 06 июня 2018

Я бы начал слева направо, я имею в виду:

создать календарь для вашего диапазона дат -> построить (если у вас его нет) список для каждой комбинации продукт-магазин -> затемсоедините эти 2 набора данных с вашей фактической таблицей, а остальное должно быть легко.

Проверьте этот подход:

DECLARE @MinDate DATE = DATEADD(DAY, -5, CONVERT(DATE, GETDATE())),
        @MaxDate DATE = CONVERT(DATE, GETDATE())

SELECT  DISTINCT
        MYDATES.DATE,
        MYDATES.STORE,
        MYDATES.PRODUCT,
        --GET LATEST PRICE FOR THE COUPLE PRODUCT-STORE IF THERE IS NOONE IN SELECTED DATE
        CASE    WHEN T.PRICE IS NULL
                THEN (  SELECT MAX(T1.PRICE)
                        FROM MYTAB T1
                        WHERE T1.STORE = MYDATES.STORE
                        AND T1.PRODUCT = MYDATES.PRODUCT
                        AND T1.DATE = ( SELECT MAX(DATE)
                                        FROM MYTAB T2
                                        WHERE T2.PRODUCT = MYDATES.PRODUCT
                                        AND T2.STORE = MYDATES.STORE))
                ELSE T.PRICE END AS PRICE, 
        CASE    WHEN T.PRICE IS NULL
                THEN 'RECOVERED FROM ' + (  SELECT CONVERT(VARCHAR, MAX(DATE), 103)
                                        FROM MYTAB T2
                                        WHERE T2.PRODUCT = MYDATES.PRODUCT
                                        AND T2.STORE = MYDATES.STORE)
                ELSE ''
                END AS [PRICE FROM]

FROM (SELECT * FROM STOREANDPRODSOURCE SP, 
(SELECT TOP (DATEDIFF(DAY, @MinDate, @MaxDate) + 1)
        Date = DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY a.object_id) - 1, @MinDate)
FROM    sys.all_objects a
        CROSS JOIN sys.all_objects b) D ) MYDATES
LEFT JOIN MYTAB T ON CONVERT(DATE, T.DATE) = MYDATES.DATE
                     AND T.PRODUCT = MYDATES.PRODUCT
                     AND T.STORE = MYDATES.STORE

Проверьте SQL Fiddle тоже

...