You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQL实现lineid='01'时docid自增的发票明细分单方法

需求背景

发票明细表现有lineid(行标识)、price €(欧元价格)两个字段,业务规则如下:

  • lineid='01'为新发票的起始行,每出现一次该值代表进入新发票,需生成新的docid(单据ID)
  • 同一张发票的非起始行,沿用当前发票的docid
    原有尝试的Case when lineid='01' then newid else id逻辑无法满足需求,需对应SQL实现方案。

原始样例数据

lineidprice €
01100.00
02200.00
0110.34
01311.12
0114.33
0236.44
0389.70
0411.33

期望输出

docidlineidprice €
101100
102200.00
20110.34
301311.12
40114.33
40236.44
40389.70
40411.33
实现方案

注意:SQL按顺序处理数据必须依赖明确的排序字段,建议先给表添加自增主键/入库时间字段作为排序依据,避免数据库返回数据顺序错乱导致docid生成错误。

支持窗口函数的数据库(MySQL8.0+、PostgreSQL、SQL Server、Oracle12c+等)

核心逻辑是按固定顺序逐行统计截至当前行lineid='01'的累计出现次数,该累计值即为符合规则的docid:

-- 假设表名为invoice_details,请将下方SQL中的<排序字段名>替换为实际用来固定行顺序的字段(如自增id、入库时间)
SELECT
    SUM(CASE WHEN lineid = '01' THEN 1 ELSE 0 END) OVER (
        ORDER BY <排序字段名>
        ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
    ) AS docid,
    lineid,
    `price €`
FROM invoice_details;

不支持窗口函数的老版本(如MySQL5.x)

通过用户变量逐行累计计数实现相同效果:

-- 先初始化计数变量
SET @doc_id := 0;
-- 逐行遍历生成docid,同样需要替换<排序字段名>
SELECT
    @doc_id := @doc_id + CASE WHEN lineid = '01' THEN 1 ELSE 0 END AS docid,
    lineid,
    `price €`
FROM invoice_details
ORDER BY <排序字段名>;

原逻辑问题说明

之前编写的Case when lineid='01' then newid else id逻辑未做累计计数,非起始行无法继承上一行的docid值,因此无法实现同发票ID沿用的效果。

内容的提问来源于stack exchange,提问作者Sokratis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 07:54:23