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

如何筛选各分类子分类下start为null且日期最早的库存记录?

解决食品库存数据库中按分类筛选最早入库空start记录的问题

问题原因分析

初始查询的问题

你的初始查询存在非聚合列未包含在GROUP BY中的核心问题:

SELECT MIN(date) as date, category, subcategory, description, code, inventory.index
FROM inventory 
WHERE start is null
GROUP BY category, subcategory

当你按category和subcategory分组时,只有这两个列和聚合函数MIN(date)的结果是确定的。而description、code、index这些列既不在分组条件里,也没有通过聚合函数处理,在多数SQL数据库(比如关闭ONLY_FULL_GROUP_BY模式的MySQL)中,会随机选取同组内某一行的对应值,这就导致了"混合行"——日期是分组内最早的,但其他列却来自同组的其他记录。

第一个嵌套SELECT方案的问题

这个写法逻辑完全错误:

SELECT * 
FROM inventory
WHERE 
( SELECT MIN(date) FROM inventory )
AND start is null
GROUP BY category, subcategory

子查询SELECT MIN(date) FROM inventory返回的是整个表的最小日期值,在WHERE条件里单独放这个值会被当作布尔值(非零即真),等价于只过滤start is null,再加上GROUP BY的原有问题,自然达不到需求。

第二个INNER JOIN方案的问题

子查询部分和初始查询犯了同样的错误:GROUP BY后选取的description、code、index是随机的,所以子查询得到的index大概率不是对应分组内MIN(date)那条记录的索引,JOIN后自然返回错误结果,甚至遗漏正确行。

正确解决方案

方案1:使用窗口函数(推荐)

用ROW_NUMBER()窗口函数给每个category+subcategory分组内的记录按date升序编号,取编号为1的记录(即日期最早的那条):

SELECT *
FROM (
    SELECT 
        *,
        ROW_NUMBER() OVER (
            PARTITION BY category, subcategory 
            ORDER BY date ASC
        ) AS rn
    FROM inventory
    WHERE start IS NULL
) AS ranked
WHERE rn = 1;

这个方法逻辑清晰,能确保返回每个分组内date最早的完整记录,不会出现混合行问题。如果同一分组内有多个记录日期完全相同,只会返回其中一条(若需返回所有相同日期的记录,可改用RANK()函数)。

方案2:关联子查询匹配分组最小日期

先找出每个category+subcategory分组内的最小date,再关联回原表找到对应完整记录:

SELECT inv.*
FROM inventory inv
WHERE 
    inv.start IS NULL
    AND inv.date = (
        SELECT MIN(date)
        FROM inventory
        WHERE 
            category = inv.category 
            AND subcategory = inv.subcategory
            AND start IS NULL
    );

这个方法不需要窗口函数,兼容不支持窗口函数的老版本数据库。如果同一分组内有多个记录日期相同,会返回所有这些记录。

方案3:JOIN分组最小日期表

先通过GROUP BY得到每个分组的最小date,再和原表JOIN匹配完整记录:

SELECT inv.*
FROM inventory inv
INNER JOIN (
    SELECT 
        category, 
        subcategory, 
        MIN(date) AS min_date
    FROM inventory
    WHERE start IS NULL
    GROUP BY category, subcategory
) AS group_min
ON 
    inv.category = group_min.category
    AND inv.subcategory = group_min.subcategory
    AND inv.date = group_min.min_date
    AND inv.start IS NULL;

这个方法和方案2逻辑类似,同样要注意同一分组内多记录日期相同的情况,会返回所有匹配记录。

内容的提问来源于stack exchange,提问作者Jefferson Paul Jones

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 10:12:29