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

多列主键最小值计算及特定账单ID销售数据查询技术问询

嘿,我来帮你梳理这两个问题的解决方案,都是实际业务里常用的思路:

一、多列联合主键的最小值计算方法

多列联合主键的最小值,核心逻辑就是按主键定义的顺序逐列比较,类似字典排序规则:先比第一列,第一列值相同再比第二列,以此类推。分两种常用场景来说:

  • 场景1:获取全表中联合主键最小的记录
    最直接的方式是按主键列排序后取首行,也可以用聚合函数组合匹配,两种方法都靠谱:

    -- 方法1:排序取首行(简洁直观)
    SELECT * FROM your_table
    ORDER BY col1, col2
    LIMIT 1;
    
    -- 方法2:聚合函数匹配最小组合(适合复杂场景)
    SELECT * FROM your_table
    WHERE (col1, col2) = (
        SELECT MIN(col1), MIN(col2) 
        FROM your_table 
        WHERE col1 = (SELECT MIN(col1) FROM your_table)
    );
    
  • 场景2:分组统计每组的最小联合主键
    如果需要按某个字段分组,取每组内主键最小的记录,用窗口函数ROW_NUMBER()是最清晰的写法:

    SELECT t.*
    FROM (
        SELECT *,
               ROW_NUMBER() OVER (PARTITION BY group_col ORDER BY pk_col1, pk_col2) AS rn
        FROM your_table
    ) t
    WHERE t.rn = 1;
    
二、特定bill_id的sales数据查询方案(处理添加后移除的情况)

先理清楚业务逻辑:sales是原账单的商品记录,sales_plus是后续的添加/移除操作,它的联合主键是sales_id+status,所以同一个sales记录(对应一个商品)可能同时存在add和remove操作,也就是你说的“添加后又被移除”的情况。

核心思路

先筛选出所有确实经历了“添加→移除”流程的sales_id(要排除只有remove没有add的无效操作),然后查询目标账单的sales数据时,排除这些已被最终移除的商品。

具体SQL实现

-- 第一步:找出所有有效移除的sales_id(添加后再移除)
WITH removed_sales AS (
    SELECT sp.sales_id
    FROM sales_plus sp
    WHERE sp.status = 'remove'
    -- 确保该商品之前有过添加操作
    AND EXISTS (
        SELECT 1 FROM sales_plus sp_add
        WHERE sp_add.sales_id = sp.sales_id
        AND sp_add.status = 'add'
        -- 可选:确保移除操作在添加之后,符合时间逻辑
        AND sp_add.time < sp.time
    )
)
-- 第二步:查询目标bill_id的商品,排除已被移除的
SELECT s.*
FROM sales s
WHERE s.bill_id = '你的目标bill_id' -- 替换成实际要查询的bill_id
AND s.id NOT IN (SELECT sales_id FROM removed_sales);

扩展:如果需要标记商品最终状态(而非排除)

如果业务需求是保留所有商品记录,但标记哪些是已移除的,可以用下面的写法:

WITH sales_final_status AS (
    SELECT 
        sp.sales_id,
        -- 判断是否存在添加后再移除的操作
        CASE 
            WHEN EXISTS (
                SELECT 1 FROM sales_plus sp2 
                WHERE sp2.sales_id = sp.sales_id 
                AND sp2.status = 'remove' 
                AND sp2.time > sp.time
            ) THEN 'removed'
            ELSE 'active'
        END AS final_status
    FROM sales_plus sp
    WHERE sp.status = 'add'
    UNION ALL
    -- 处理只有移除没有添加的无效操作
    SELECT 
        sp.sales_id,
        'invalid_remove' AS final_status
    FROM sales_plus sp
    WHERE sp.status = 'remove'
    AND NOT EXISTS (
        SELECT 1 FROM sales_plus sp2 
        WHERE sp2.sales_id = sp.sales_id 
        AND sp2.status = 'add'
    )
)
SELECT 
    s.*,
    -- 原商品没有后续操作的话,标记为original
    COALESCE(ss.final_status, 'original') AS final_status
FROM sales s
LEFT JOIN sales_final_status ss ON s.id = ss.sales_id
WHERE s.bill_id = '你的目标bill_id';

关键说明

  • 加入sp_add.time < sp.time是为了符合业务逻辑:移除操作必须在添加之后,避免乱序的无效操作影响结果
  • 用CTE(公共表表达式)拆分逻辑,让SQL更易读、易维护

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:47:21