Sql 显示最新的视图 + 如果数据集中不存在,则为第一天创建行
Sql view that shows latest + creates row for first day if not present in dataset
我有以下数据:
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 天的条目。因此,如果在 today-X 天没有某个商店和产品对的条目,我需要找到该对的最新价格(如果存在),然后将该价格复制到 date = today - X 的行中。这有意义吗?
我会从左到右开始,我的意思是:
为你的日期范围建立一个日历 -> 建立(如果你没有)每个产品商店组合的列表 -> 然后将这 2 个数据集与你的实际 table 结合起来,其余的应该是简单。
检查此方法:
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
如果我理解这个问题,那么对于这个样本数据
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
OP 想要显示 ('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
我有以下数据:
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 天的条目。因此,如果在 today-X 天没有某个商店和产品对的条目,我需要找到该对的最新价格(如果存在),然后将该价格复制到 date = today - X 的行中。这有意义吗?
我会从左到右开始,我的意思是:
为你的日期范围建立一个日历 -> 建立(如果你没有)每个产品商店组合的列表 -> 然后将这 2 个数据集与你的实际 table 结合起来,其余的应该是简单。
检查此方法:
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
如果我理解这个问题,那么对于这个样本数据
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
OP 想要显示 ('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