Select 个值在两个时间戳之间具有负差并在 table 中显示它们的完整历史记录
Select values that have a minus difference between two timestamps and show their complete history in the table
CREATE TABLE logistics (
id SERIAL PRIMARY KEY,
time_stamp DATE,
product VARCHAR(255),
quantity INT
);
INSERT INTO logistics
(time_stamp, product, quantity)
VALUES
('2020-01-14', 'Product_A', '100'),
('2020-01-14', 'Product_B', '300'),
('2020-01-15', 'Product_B', '400'),
('2020-01-15', 'Product_C', '350'),
('2020-01-16', 'Product_B', '530'),
('2020-01-16', 'Product_C', '250'),
('2020-01-16', 'Product_D', '670'),
('2020-01-17', 'Product_C', '380'),
('2020-01-17', 'Product_D', '980'),
('2020-01-17', 'Product_E', '700'),
('2020-01-17', 'Product_F', '450');
预期结果
time_stamp | product | difference |
------------|-----------------|-----------------|---------
2020-01-15 | Product_C | 350 |
2020-01-16 | Product_C | -100 |
2020-01-17 | Product_C | 130 |
我想做以下两件事:
- 从 table 中提取数量从时间戳减少到时间戳
的产品
- 显示所有时间戳中这些产品的历史记录。
通过以下查询,我可以执行第 1 步,但我想知道我需要如何修改它以包含所选产品的历史记录。
SELECT
t1.time_stamp AS time_stamp,
t1.product AS product,
SUM(t1.difference) AS difference
FROM
(SELECT
l.time_stamp AS time_stamp,
l.product AS product,
Coalesce(l.quantity-LAG(l.quantity) OVER (Partition by l.product ORDER BY l.product, l.time_stamp), l.quantity) AS difference
FROM logistics l
ORDER BY 1,2) t1
WHERE t1.difference < 0
GROUP BY 1,2
ORDER BY 1,2;
你有什么想法吗?
使用EXISTS
:
WITH cte AS (
SELECT time_stamp, product,
quantity - LAG(quantity, 1, 0) OVER (PARTITION BY product ORDER BY time_stamp) difference
FROM logistics
)
SELECT c1.*
FROM cte c1
WHERE EXISTS (
SELECT 1
FROM cte c2
WHERE c2.product = c1.product AND c2.difference < 0
)
ORDER BY c1.product, c1.time_stamp;
参见demo。
您可以使用 MAX OVER
计算每个产品的标志。
然后在标志上过滤。
SELECT q2.time_stamp, q2.product, q2.difference
FROM (
SELECT q1.*
, MAX(CASE WHEN q1.quantity < q1.prev_quantity THEN 1 ELSE 0 END)
OVER (PARTITION BY q1.product) AS has_difference
, (q1.quantity - coalesce(q1.prev_quantity, 0)) AS difference
FROM (
SELECT l.product, l.time_stamp, l.quantity
, LAG(l.quantity) OVER (PARTITION BY l.product ORDER BY l.time_stamp) AS prev_quantity
FROM logistics l
) AS q1
) q2
WHERE q2.has_difference = 1
ORDER BY q2.product, q2.time_stamp;
time_stamp | product | difference
:--------- | :-------- | ---------:
2020-01-15 | Product_C | 350
2020-01-16 | Product_C | -100
2020-01-17 | Product_C | 130
db<>fiddle here
WITH cte AS
(SELECT
l.time_stamp AS time_stamp,
l.product AS product,
Coalesce(l.quantity-LAG(l.quantity) OVER (Partition by l.product ORDER BY l.product, l.time_stamp), l.quantity) AS difference
FROM logistics l
ORDER BY 1,2)
SELECT
t1.time_stamp AS time_stamp,
t1.product AS product,
SUM(t1.difference) AS difference
FROM cte t1
WHERE EXISTS
(SELECT
t2.product AS product
FROM cte t2
WHERE t2.difference < 0
AND t2.product = t1.product
GROUP BY 1
ORDER BY 1)
GROUP BY 1,2
ORDER BY 1,2;
CREATE TABLE logistics (
id SERIAL PRIMARY KEY,
time_stamp DATE,
product VARCHAR(255),
quantity INT
);
INSERT INTO logistics
(time_stamp, product, quantity)
VALUES
('2020-01-14', 'Product_A', '100'),
('2020-01-14', 'Product_B', '300'),
('2020-01-15', 'Product_B', '400'),
('2020-01-15', 'Product_C', '350'),
('2020-01-16', 'Product_B', '530'),
('2020-01-16', 'Product_C', '250'),
('2020-01-16', 'Product_D', '670'),
('2020-01-17', 'Product_C', '380'),
('2020-01-17', 'Product_D', '980'),
('2020-01-17', 'Product_E', '700'),
('2020-01-17', 'Product_F', '450');
预期结果
time_stamp | product | difference |
------------|-----------------|-----------------|---------
2020-01-15 | Product_C | 350 |
2020-01-16 | Product_C | -100 |
2020-01-17 | Product_C | 130 |
我想做以下两件事:
- 从 table 中提取数量从时间戳减少到时间戳
- 显示所有时间戳中这些产品的历史记录。
通过以下查询,我可以执行第 1 步,但我想知道我需要如何修改它以包含所选产品的历史记录。
SELECT
t1.time_stamp AS time_stamp,
t1.product AS product,
SUM(t1.difference) AS difference
FROM
(SELECT
l.time_stamp AS time_stamp,
l.product AS product,
Coalesce(l.quantity-LAG(l.quantity) OVER (Partition by l.product ORDER BY l.product, l.time_stamp), l.quantity) AS difference
FROM logistics l
ORDER BY 1,2) t1
WHERE t1.difference < 0
GROUP BY 1,2
ORDER BY 1,2;
你有什么想法吗?
使用EXISTS
:
WITH cte AS (
SELECT time_stamp, product,
quantity - LAG(quantity, 1, 0) OVER (PARTITION BY product ORDER BY time_stamp) difference
FROM logistics
)
SELECT c1.*
FROM cte c1
WHERE EXISTS (
SELECT 1
FROM cte c2
WHERE c2.product = c1.product AND c2.difference < 0
)
ORDER BY c1.product, c1.time_stamp;
参见demo。
您可以使用 MAX OVER
计算每个产品的标志。
然后在标志上过滤。
SELECT q2.time_stamp, q2.product, q2.difference FROM ( SELECT q1.* , MAX(CASE WHEN q1.quantity < q1.prev_quantity THEN 1 ELSE 0 END) OVER (PARTITION BY q1.product) AS has_difference , (q1.quantity - coalesce(q1.prev_quantity, 0)) AS difference FROM ( SELECT l.product, l.time_stamp, l.quantity , LAG(l.quantity) OVER (PARTITION BY l.product ORDER BY l.time_stamp) AS prev_quantity FROM logistics l ) AS q1 ) q2 WHERE q2.has_difference = 1 ORDER BY q2.product, q2.time_stamp;
time_stamp | product | difference :--------- | :-------- | ---------: 2020-01-15 | Product_C | 350 2020-01-16 | Product_C | -100 2020-01-17 | Product_C | 130
db<>fiddle here
WITH cte AS
(SELECT
l.time_stamp AS time_stamp,
l.product AS product,
Coalesce(l.quantity-LAG(l.quantity) OVER (Partition by l.product ORDER BY l.product, l.time_stamp), l.quantity) AS difference
FROM logistics l
ORDER BY 1,2)
SELECT
t1.time_stamp AS time_stamp,
t1.product AS product,
SUM(t1.difference) AS difference
FROM cte t1
WHERE EXISTS
(SELECT
t2.product AS product
FROM cte t2
WHERE t2.difference < 0
AND t2.product = t1.product
GROUP BY 1
ORDER BY 1)
GROUP BY 1,2
ORDER BY 1,2;