How to create a SQL cumulative query to show if has balance for a sale considering another sales for same item

huangapple go评论107阅读模式
英文:

How to create a SQL cumulative query to show if has balance for a sale considering another sales for same item

问题

以下是翻译的部分内容:

  1. 考虑 `sales` 表:
  2. | sale_id | item_id | quantity | sale_date |
  3. |---------|---------|---------:|------------|
  4. | 100 | P1 | 5 | 2023-02-18 |
  5. | 101 | P1 | 4 | 2023-02-17 |
  6. | 103 | B2 | 7 | 2023-02-19 |
  7. | 104 | P1 | 1 | 2023-02-20 |
  8. `stock_balance` 表:
  9. | item_id | balance |
  10. |---------|--------:|
  11. | P1 | 6 |
  12. | B2 | 5 |
  13. 我想创建一个 SQL 查询,显示哪个销售订单具有要交付的余额,较早的销售订单具有优先权。此查询将生成以下结果
  14. | sale_id | item_id | quantity | sale_date | balance_start | has_balance | reserved | balance_end |
  15. |---------|---------|---------:|------------|--------------:|-------------|---------:|------------:|
  16. | 103 | B2 | 7 | 2023-02-19 | 5 | false | 0 | 5 |
  17. | 101 | P1 | 4 | 2023-02-17 | 6 | true | 4 | 2 |
  18. | 100 | P1 | 5 | 2023-02-18 | 2 | false | 0 | 2 |
  19. | 104 | P1 | 1 | 2023-02-20 | 2 | true | 1 | 1 |
  20. 我尝试创建以下查询
  21. ```sql
  22. with sale_reserved as (
  23. SELECT
  24. s1.*,
  25. sb.balance as balance_start,
  26. CASE
  27. WHEN s1.quantity <= sb.balance AND sb.balance - s1.quantity >= (
  28. SELECT COALESCE(SUM(s2.quantity), 0)
  29. FROM sales s2
  30. WHERE s2.item_id = s1.item_id AND s2.sale_date < s1.sale_date
  31. ) THEN s1.quantity
  32. ELSE 0
  33. END AS reserved
  34. FROM
  35. sales s1
  36. JOIN stock_balance sb ON s1.item_id = sb.item_id
  37. )
  38. select
  39. sale_id, item_id, quantity, sale_date , balance_start,
  40. reserved>0 as has_balance,
  41. reserved,
  42. (balance_start-reserved) as balance_end
  43. from sale_reserved
  44. ORDER BY item_id, sale_date;

这将产生:

sale_id item_id quantity sale_date balance_start has_balance reserved balance_end
103 B2 7 2023-02-19 5 false 0 5
101 P1 4 2023-02-17 6 true 4 2
100 P1 5 2023-02-18 6 false 0 6
104 P1 1 2023-02-20 6 false 0 6

可以看到起始余额不正确,销售订单 '104' 具有余额并显示为 false。

英文:

Consider the sales table:

sale_id item_id quantity sale_date
100 P1 5 2023-02-18
101 P1 4 2023-02-17
103 B2 7 2023-02-19
104 P1 1 2023-02-20

the stock_balance table:

item_id balance
P1 6
B2 5

I want to create a sql query to show what sale has balance to be delivered, the older sale has priority.
This query will produce the following result

sale_id item_id quantity sale_date balance_start has_balance reserved balance_end
103 B2 7 2023-02-19 5 false 0 5
101 P1 4 2023-02-17 6 true 4 2
100 P1 5 2023-02-18 2 false 0 2
104 P1 1 2023-02-20 2 true 1 1

I try to create the following query

  1. with sale_reserved as (
  2. SELECT
  3. s1.*,
  4. sb.balance as balance_start,
  5. CASE
  6. WHEN s1.quantity <= sb.balance AND sb.balance - s1.quantity >= (
  7. SELECT COALESCE(SUM(s2.quantity), 0)
  8. FROM sales s2
  9. WHERE s2.item_id = s1.item_id AND s2.sale_date < s1.sale_date
  10. ) THEN s1.quantity
  11. ELSE 0
  12. END AS reserved
  13. FROM
  14. sales s1
  15. JOIN stock_balance sb ON s1.item_id = sb.item_id
  16. )
  17. select
  18. sale_id, item_id, quantity, sale_date , balance_start,
  19. reserved>0 as has_balance,
  20. reserved,
  21. (balance_start-reserved) as balance_end
  22. from sale_reserved
  23. ORDER BY item_id, sale_date;

this will produce:

sale_id item_id quantity sale_date balance_start has_balance reserved balance_end
103 B2 7 2023-02-19 5 false 0 5
101 P1 4 2023-02-17 6 true 4 2
100 P1 5 2023-02-18 6 false 0 6
104 P1 1 2023-02-20 6 false 0 6

You can see the balance start is not correct and the sale '104' has balance and show false

答案1

得分: 1

您可以使用递归的cte(公共表达式)来实现:

  1. with recursive cte(sale_id, item_id, m, quantity, balance_start, has_balance, reserved, balance_end) as (
  2. select s.sale_id, s1.item_id, s1.m, s.quantity, b.balance, b.balance >= s.quantity,
  3. case when b.balance >= s.quantity then s.quantity else 0 end,
  4. case when b.balance >= s.quantity then b.balance - s.quantity else b.balance end
  5. from (select s.item_id, min(s.sale_date) m from sales s group by s.item_id) s1
  6. join sales s on s.item_id = s1.item_id and s.sale_date = date(s1.m)
  7. join stock_balance b on b.item_id = s1.item_id
  8. union all
  9. select s2.sale_id, c.item_id, s2.sale_date, s2.quantity, c.balance_end, c.balance_end >= s2.quantity,
  10. case when c.balance_end >= s2.quantity then s2.quantity else 0 end,
  11. case when c.balance_end >= s2.quantity then c.balance_end - s2.quantity else c.balance_end end
  12. from cte c
  13. cross join lateral (select s.* from sales s where s.item_id = c.item_id
  14. and s.sale_date = (select min(s1.sale_date) from sales s1 where s1.item_id = c.item_id and s1.sale_date > c.m)) s2
  15. )
  16. select c.sale_id, c.item_id, c.quantity, c.m sale_date, c.balance_start, c.has_balance, c.reserved, c.balance_end
  17. from cte c order by c.item_id, c.m

查看示例

英文:

You can use a recursive cte:

  1. with recursive cte(sale_id, item_id, m, quantity, balance_start, has_balance, reserved, balance_end) as (
  2. select s.sale_id, s1.item_id, s1.m, s.quantity, b.balance, b.balance >= s.quantity,
  3. case when b.balance >= s.quantity then s.quantity else 0 end,
  4. case when b.balance >= s.quantity then b.balance - s.quantity else b.balance end
  5. from (select s.item_id, min(s.sale_date) m from sales s group by s.item_id) s1
  6. join sales s on s.item_id = s1.item_id and s.sale_date = date(s1.m)
  7. join stock_balance b on b.item_id = s1.item_id
  8. union all
  9. select s2.sale_id, c.item_id, s2.sale_date, s2.quantity, c.balance_end, c.balance_end >= s2.quantity,
  10. case when c.balance_end >= s2.quantity then s2.quantity else 0 end,
  11. case when c.balance_end >= s2.quantity then c.balance_end - s2.quantity else c.balance_end end
  12. from cte c
  13. cross join lateral (select s.* from sales s where s.item_id = c.item_id
  14. and s.sale_date = (select min(s1.sale_date) from sales s1 where s1.item_id = c.item_id and s1.sale_date > c.m)) s2
  15. )
  16. select c.sale_id, c.item_id, c.quantity, c.m sale_date, c.balance_start, c.has_balance, c.reserved, c.balance_end
  17. from cte c order by c.item_id, c.m

See fiddle

huangapple
  • 本文由 发表于 2023年2月19日 21:18:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/75500409.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定