入库日期/项目/产品/数量
1/1 A 香蕉 100
1/2 B 苹果 100
1/3 A 香蕉 100
出库日期/项目/产品/数量
1/3 A 香蕉 50
1/4 A 香蕉 150
得出结果
项目/入库日期/入库数量/出库日期/出库数量
A 1/1 100 1/3 50
A 1/1 100 1/4 50
A 1/3 100 1/4 100
1)较短的文本:
char
varchar
其他:
binary和varbinary用于保存较短的二进制
enum用于保存枚举
set用于保存集合
2)较长的文本:
特点:
写法 | M的意思 | 特点 | 空间的耗费 | 效率 |
---|---|---|---|---|
char(M) | 最大的字符数,可以省略,默认为1 | 固定长度的字符 | 比较耗费 | 高 |
varchar(M) | 最大的字符数,不可以省略 | 可变长度的字符 | 比较节省 | 低 |
CREATE TABLE tab_char(
c1 ENUM('a','b','c')
);
INSERT INTO tab_char VALUES('a');
INSERT INTO tab_char VALUES('b');
INSERT INTO tab_char VALUES('c');
INSERT INTO tab_char VALUES('m');
INSERT INTO tab_char VALUES('A');
SELECT * FROM tab_set;
CREATE TABLE tab_set(
s1 SET('a','b','c','d')
);
INSERT INTO tab_set VALUES('a');
INSERT INTO tab_set VALUES('A,B');
INSERT INTO tab_set VALUES('a,c,d');
1、实际处理比想象的复杂,我也只是模拟了稍微复制的数据(生产数据可能更为复杂,我只做抛砖引玉)(在MySQL 8中运行通过):
WITH rk AS ( SELECT '2023-01-01' rq, 'A' xm, '香蕉' cp, 100 sl UNION ALL
SELECT '2023-01-02' rq, 'B' xm, '苹果' cp, 100 sl UNION ALL
SELECT '2023-01-03' rq, 'A' xm, '香蕉' cp, 200 sl UNION ALL
SELECT '2023-01-03' rq, 'B' xm, '苹果' cp, 100 sl )
, ck AS ( SELECT '2023-01-03' rq, 'A' xm, '香蕉' cp, 50 sl UNION ALL
SELECT '2023-01-03' rq, 'B' xm, '苹果' cp, 100 sl UNION ALL
SELECT '2023-01-04' rq, 'A' xm, '香蕉' cp, 60 sl UNION ALL
SELECT '2023-01-04' rq, 'B' xm, '苹果' cp, 100 sl UNION ALL
SELECT '2023-01-05' rq, 'A' xm, '香蕉' cp, 150 sl )
, rk0 AS (
SELECT *, sum( sl ) OVER( PARTITION BY xm, cp ORDER BY rq ) ljrk FROM rk )
, rk1 AS (
SELECT *, LAG( ljrk, 1, 0 ) OVER( PARTITION BY xm, cp ORDER BY rq ) scljrk FROM rk0 )
, ck0 AS (
SELECT *, sum( sl ) OVER( PARTITION BY xm, cp ORDER BY rq ) ljck FROM ck )
, ck1 AS (
SELECT *, LAG( ljck, 1, 0 ) OVER( PARTITION BY xm, cp ORDER BY rq ) scljck FROM ck0 )
SELECT rk.xm, rk.rq rkrq, rk.sl rksl, ck.rq ckrq -- , rk.cp, ck.sl cksl, rk.ljrk, ck.ljck, ck.ljck - rk.ljrk sy, rk.scljrk, ck.scljck
, ( CASE WHEN ck.ljck > rk.ljrk THEN rk.ljrk - ck.scljck
WHEN ck.ljck - rk.scljrk < ck.sl THEN ck.ljck - rk.scljrk
ELSE ck.sl END ) cksl
FROM rk1 rk LEFT JOIN ck1 ck ON rk.rq <= ck.rq AND rk.xm = ck.xm AND rk.cp = ck.cp AND ck.ljck > rk.scljrk
WHERE ck.ljck < rk.ljrk + ck.sl
ORDER BY rk.xm, rk.cp, rk.rq, ck.rq
入库模拟数据:
出库模拟数据:
查询结果数据:
2、SQL中,如果你的项目与产品一一对应,所有的PARTITION BY 中只使用项目一个字段即可,否则,必须使用两个字段作为PARTITION BY 条件