Mysql 根据日期查找行总数的复杂查询
我有上表的库存记录。我想要两样东西: 给定@date的当前值。因此,如果我的给定日期是2021-03-09,即使该日期不在列表中,它也会给出所有ABC、XYZ和KLM项目的最新值及其当前状态。因此,select表将如下所示: 类似地,我希望获得当前值,但对于特定的时间范围,给定now date@date,其中该日期可以是任何日期。所以如果@date=2021-4-1,我在寻找这样的东西: 需要注意的一点是,如果有扣减,旧项目将被扣减。因此,如果50天前增加了5x项XYZ,20天前增加了2x项XYZ,10天前减少了3x项XYZ,则该表将显示总计=4,0-30天=2,31-60天=2,因为即使最近发生了扣除,旧项也被扣除 我的第一个猜测是利用分区,但我不确定这是否可行,因为我知道分区之外的值会受到影响 编辑: 在一位朋友指出后,我找到了回答问题第一部分的方法:Mysql 根据日期查找行总数的复杂查询,mysql,sql,Mysql,Sql,我有上表的库存记录。我想要两样东西: 给定@date的当前值。因此,如果我的给定日期是2021-03-09,即使该日期不在列表中,它也会给出所有ABC、XYZ和KLM项目的最新值及其当前状态。因此,select表将如下所示: 类似地,我希望获得当前值,但对于特定的时间范围,给定now date@date,其中该日期可以是任何日期。所以如果@date=2021-4-1,我在寻找这样的东西: 需要注意的一点是,如果有扣减,旧项目将被扣减。因此,如果50天前增加了5x项XYZ,20天前增加了2x项XY
+------+-------+-----------+------------+------------+----------+
| item | total | 0-30 days | 31-60 days | 61-90 days | 90+ days |
+======+=======+===========+============+============+==========+
| XYZ | 5 | 1 | 4 | 0 | 0 |
+------+-------+-----------+------------+------------+----------+
| ABC | 11 | 0 | 0 | 11 | 0 |
+------+-------+-----------+------------+------------+----------+
| KLM | 0 | 0 | 0 | 0 | 0 |
+------+-------+-----------+------------+------------+----------+
为回答你的问题的第一部分,考虑下面……/P>
SELECT
item,
MAX(curr) as current // needed to group item columns
FROM(
SELECT
*,
LAST_VALUE(current) OVER // partitioning was needed to
( // find the most recent 'current'
PARTITION BY item // value added on that 'item'
ORDER BY date
RANGE BETWEEN
UNBOUNDED PRECEDING AND
UNBOUNDED FOLLOWING
) curr
FROM tbl
WHERE date <= @date
)a
WHERE bal = balance
GROUP BY item
;
我们还可以使用常用的表表达式/窗口函数来解决这个问题,当我们来研究问题的下一部分时,这可能会很有用——尽管我怀疑其中的大部分问题应该在应用程序代码中解决。请参阅@草莓谢谢你的提示,使用“创建和插入”查询编辑问题,以实现可复制性。我希望你能帮我解决这个问题的任何部分?你是说我应该提供我试图做的事情吗?我知道我的答案是错误的,因为它没有聚合正确的信息。我根本不知道怎么做。我还认为我的答案会更加混乱和分散注意力。根据我最初评论的链接答案,知道你能做什么让我们知道从哪里开始回答。
+------+-------+-----------+------------+------------+----------+
| item | total | 0-30 days | 31-60 days | 61-90 days | 90+ days |
+======+=======+===========+============+============+==========+
| XYZ | 5 | 1 | 4 | 0 | 0 |
+------+-------+-----------+------------+------------+----------+
| ABC | 11 | 0 | 0 | 11 | 0 |
+------+-------+-----------+------------+------------+----------+
| KLM | 0 | 0 | 0 | 0 | 0 |
+------+-------+-----------+------------+------------+----------+
SELECT
item,
MAX(curr) as current // needed to group item columns
FROM(
SELECT
*,
LAST_VALUE(current) OVER // partitioning was needed to
( // find the most recent 'current'
PARTITION BY item // value added on that 'item'
ORDER BY date
RANGE BETWEEN
UNBOUNDED PRECEDING AND
UNBOUNDED FOLLOWING
) curr
FROM tbl
WHERE date <= @date
)a
WHERE bal = balance
GROUP BY item
;
CREATE TABLE master_tb
( date DATE
, item VARCHAR(10)
, change_x INT
, current INT
, PRIMARY KEY(date,item)
);
INSERT INTO master_tb (date, item, change_x, current)
VALUES
("2021-01-01", "ABC", 11, 11),
("2021-01-01", "KLM", 4, 4),
("2021-01-02", "KLM", -3, 1),
("2021-01-03", "KLM", -1, 0),
("2021-02-01", "KLM", 6, 6),
("2021-02-02", "XYZ", 5, 5),
("2021-02-08", "KLM", -3, 3),
("2021-02-09", "XYZ", -1, 4),
("2021-03-02", "XYZ", 2, 6),
("2021-03-08", "XYZ", -1, 5),
("2021-03-08", "KLM", -3, 0);
SELECT item
, MAX(date) date
FROM master_tb
WHERE date <= '2021-03-09'
GROUP
BY item;
+------+------------+
| item | date |
+------+------------+
| ABC | 2021-01-01 |
| KLM | 2021-03-08 |
| XYZ | 2021-03-08 |
+------+------------+
SELECT a.*
FROM master_tb a
JOIN
( SELECT item
, MAX(date) date
FROM master_tb
WHERE date <= '2021-03-09'
GROUP
BY item
) b
ON b.item = a.item
AND b.date = a.date;
+------------+------+----------+---------+
| date | item | change_x | current |
+------------+------+----------+---------+
| 2021-01-01 | ABC | 11 | 11 |
| 2021-03-08 | KLM | -3 | 0 |
| 2021-03-08 | XYZ | -1 | 5 |
+------------+------+----------+---------+