MYSQL写先进先出

入库日期/项目/产品/数量

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

  • 这篇博客: 八、一篇文章快速搞懂MySQL 常见的数据类型(整型、小数、字符型、日期型详解)中的 三、字符型 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 1)较短的文本:

    • char

    • varchar

    • 其他:
      binary和varbinary用于保存较短的二进制
      enum用于保存枚举
      set用于保存集合

    2)较长的文本:

    • text
    • blob(较大的二进制)

    特点:

    写法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

入库模拟数据:

img

出库模拟数据:

img

查询结果数据:

img

2、SQL中,如果你的项目与产品一一对应,所有的PARTITION BY 中只使用项目一个字段即可,否则,必须使用两个字段作为PARTITION BY 条件