Select 个值在两个时间戳之间具有负差并在 table 中显示它们的完整历史记录

Select values that have a minus difference between two timestamps and show their complete history in the table

DB-Fiddle

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      |

我想做以下两件事:

  1. 从 table 中提取数量从时间戳减少到时间戳
  2. 的产品
  3. 显示所有时间戳中这些产品的历史记录。

通过以下查询,我可以执行第 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

DB-Fiddle

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;