我有一个简单的库存表:
IF OBJECT_ID('tempdb.dbo.#t') IS NOT NULL
DROP TABLE #t
GO
CREATE TABLE #t
(
[date] DATE,
Item VARCHAR(1),
[Location] INT,
Qty INT
)
INSERT INTO #t ([date], [Item], [Location], [Qty])
VALUES ('2017-11-16', 'A', 1, 5),
('2017-11-16', 'B', 1, 5),
('2017-11-16', 'B', 2, 10),
('2017-11-16', 'A', 3, 1),
('2017-11-16', 'C', 3, 2),
('2017-11-16', 'A', 4, 20),
('2017-11-15', 'A', 1, 5),
('2017-11-15', 'B', 1, 5),
('2017-11-15', 'B', 2, 10),
('2017-11-15', 'A', 3, 1),
('2017-11-15', 'C', 3, 8),
('2017-11-14', 'A', 1, 10),
('2017-11-14', 'B', 1, 1),
('2017-11-14', 'B', 2, 10),
('2017-11-14', 'A', 3, 1),
('2017-11-14', 'C', 3, 8)
我想找出日期(在where子句中)以及过去的位置项级别的数量差异。
因此结果如下:
+------------+------+----------+-----+------------+---------+
| Date | Item | Location | Qty | LastChange | LastQty |
+------------+------+----------+-----+------------+---------+
| 16.11.2017 | A | 1 | 5 | 14.11.2017 | 10 |
| 16.11.2017 | B | 1 | 5 | 14.11.2017 | 1 |
| 16.11.2017 | B | 2 | 10 | | |
| 16.11.2017 | A | 3 | 1 | | |
| 16.11.2017 | C | 3 | 2 | 15.11.2017 | 8 |
| 16.11.2017 | A | 4 | 20 | | |
+------------+------+----------+-----+------------+---------+
由于库存表非常大,我想尽可能避免使用窗口函数。
我已自行加入库存表。但是,我在找到消除不相关数据集的条款时遇到了问题。
SELECT
a.[date],
a.Item,
a.Location,
a.qty,
b.[date] LastChange,
b.qty LastQty
FROM
#t a
LEFT JOIN
#t b ON a.Item = b.Item
AND a.location = b.location
AND b.date < a.date
WHERE
a.date = '2017-11-16'
答案 0 :(得分:2)
您需要额外的LEFT JOIN
才能消除冗余记录:
SELECT a.[date], a.Item, a.Location, a.qty,
b.[date] LastChange, b.qty LastQty
FROM t AS a
LEFT JOIN t AS b
ON a.Item = b.Item AND a.location = b.location AND b.date < a.date AND a.qty != b.qty
LEFT JOIN t AS c
ON c.Item = b.Item AND c.location = b.location AND c.date < b.date
WHERE
a.[date] = '2017-11-16' AND c.Item IS NULL
使用
LEFT JOIN t AS c
ON c.Item = b.Item AND c.location = b.location AND c.date < b.date
结合
WHERE
... AND c.Item IS NULL
就像是这样说:给我那些没有其他b
记录的c
记录,并提供更早的记录。
使用FIRST_VALUE
窗口功能:
;WITH CTE AS (
SELECT [date], [Item], [Location], [Qty],
FIRST_VALUE([date]) OVER (PARTITION BY [Item], [Location]
ORDER BY [date]) AS LastChange,
FIRST_VALUE([Qty]) OVER (PARTITION BY [Item], [Location]
ORDER BY [date]) AS LastQty
FROM t
)
SELECT [date], [Item], [Location], [Qty],
IIF([Qty] != [LastQty], LastChange, NULL) AS LastChange,
IIF([Qty] != [LastQty], LastQty, NULL) AS LastQty
FROM CTE
WHERE [date] = '2017-11-16'
答案 1 :(得分:1)
尝试此查询
DECLARE @ReportDate date='20171116'
SELECT
curData.[date],
curData.Item,
curData.Location,
curData.Qty,
lastData.[date] LastChange,
lastData.Qty LastQty
FROM
(
SELECT *
FROM #t
WHERE [date]=@ReportDate
) curData
OUTER APPLY
(
SELECT TOP 1 *
FROM #t lastData
WHERE lastData.Item=curData.Item
AND lastData.Location=curData.Location
AND lastData.[date]<curData.[date]
AND lastData.Qty<>curData.Qty
ORDER BY lastData.[date] DESC
) lastData