如何在SQL中创建查询仓库库存日环比低于20%商品的视图
解决方法:创建库存占比低于20%的商品视图
没问题,我来帮你搞定这个需求!核心思路是先获取每个商品在对应仓库中前一日的库存数量,再计算当日库存与前一日的占比,最后筛选出占比低于20%的记录并封装成视图。
前提假设
根据你提供的表结构截图,我假设你的数据库中有以下核心表(如果表名/字段名不同,直接替换即可):
inventory:库存记录表,包含warehouse_id(仓库ID)、product_id(商品ID)、stock_date(库存日期)、stock_quantity(库存数量)warehouse:仓库信息表,包含warehouse_id、warehouse_name(仓库名称)product:商品信息表,包含product_id、product_name(商品名称)
方法一:使用LATERAL JOIN(适合PostgreSQL等支持的数据库)
这种方式可以精准匹配前一日的库存记录,避免日期不连续的问题:
CREATE VIEW low_stock_ratio_products AS SELECT w.warehouse_name, p.product_name, i.stock_date, i.stock_quantity AS current_stock, prev_stock.stock_quantity AS previous_stock, ROUND((i.stock_quantity::FLOAT / prev_stock.stock_quantity), 4) AS stock_ratio FROM inventory i -- 关联获取同一仓库、同一商品的前一日库存 JOIN LATERAL ( SELECT stock_quantity FROM inventory WHERE warehouse_id = i.warehouse_id AND product_id = i.product_id AND stock_date = i.stock_date - INTERVAL '1 day' ) prev_stock ON TRUE -- 关联仓库表获取名称 JOIN warehouse w ON i.warehouse_id = w.warehouse_id -- 关联商品表获取名称 JOIN product p ON i.product_id = p.product_id -- 筛选条件:前一日库存不为0,且当日库存占比低于20% WHERE prev_stock.stock_quantity > 0 AND (i.stock_quantity::FLOAT / prev_stock.stock_quantity) < 0.2 ORDER BY i.stock_date DESC, w.warehouse_name, p.product_name;
方法二:使用窗口函数LAG()(适合MySQL 8.0+、PostgreSQL、SQL Server等)
如果你的数据库支持窗口函数,这种写法更简洁:
CREATE VIEW low_stock_ratio_products AS WITH inventory_with_prev_stock AS ( SELECT warehouse_id, product_id, stock_date, stock_quantity, -- 按仓库+商品分区,按日期排序,获取前一条记录的库存 LAG(stock_quantity) OVER (PARTITION BY warehouse_id, product_id ORDER BY stock_date) AS previous_stock FROM inventory ) SELECT w.warehouse_name, p.product_name, inv.stock_date, inv.stock_quantity AS current_stock, inv.previous_stock, ROUND((inv.stock_quantity::FLOAT / inv.previous_stock), 4) AS stock_ratio FROM inventory_with_prev_stock inv JOIN warehouse w ON inv.warehouse_id = w.warehouse_id JOIN product p ON inv.product_id = p.product_id WHERE inv.previous_stock IS NOT NULL -- 排除没有前一日数据的初始记录 AND inv.previous_stock > 0 -- 避免除以0错误 AND (inv.stock_quantity::FLOAT / inv.previous_stock) < 0.2 ORDER BY inv.stock_date DESC, w.warehouse_name, p.product_name;
注意事项
- 请根据实际表名/字段名替换代码中的对应名称,比如如果库存表叫
stock_records,直接替换即可。 - 转换为
FLOAT是为了避免整数除法导致的错误(比如整数1除以5会得到0,而不是0.2)。 - 如果你的日期字段是
DATE类型,INTERVAL '1 day'可能需要调整为对应数据库的语法(比如MySQL用DATE_SUB(i.stock_date, INTERVAL 1 DAY))。
内容的提问来源于stack exchange,提问作者k_dadun
相关产品推荐
相关产品推荐

