三张表:商品表、库存表、出库表。查询库存为0的记录。可否再优化一下SQL?

商品表结构 goods

create table goods
(
    id          bigint unsigned auto_increment
        primary key,
    name        varchar(255) default '' not null comment '货物名称',
    category_id int          default 0  not null comment '货物分类ID',
    image       varchar(255)            null comment '货物图片',
    content     text                    null comment '货物介绍',
    created_at  timestamp               null,
    updated_at  timestamp               null
)
    comment '货物表' collate = utf8mb4_unicode_ci;
INSERT INTO goods (id, name, category_id, user_id, image, content, created_at, updated_at) VALUES (1, '华为 HUAWEI Mate 30 5G 麒麟990 4000万超感光徕卡影像双超级快充8GB+128GB亮黑色5G全网通游戏手机', 4, 7, null, null, '2020-10-13 17:49:21', '2020-10-14 14:10:49');
INSERT INTO goods (id, name, category_id, image, content, created_at, updated_at) VALUES (2, '货物02', 3, null, null, '2020-10-13 20:51:40', '2020-10-13 20:51:40');
INSERT INTO goods (id, name, category_id, image, content, created_at, updated_at) VALUES (3, '货物03', 4, null, null, '2020-10-13 20:52:35', '2020-10-13 20:52:35');
INSERT INTO goods (id, name, category_id, image, content, created_at, updated_at) VALUES (4, '货物04', 4, null, null, '2020-10-13 21:07:26', '2020-10-13 21:07:26');
INSERT INTO goods (id, name, category_id, image, content, created_at, updated_at) VALUES (5, '货物06', 5, null, '货物哦', '2020-10-13 21:22:17', '2020-10-13 21:22:34');

库存表结构 inventories

create table inventories
(
    id             bigint unsigned auto_increment
        primary key,
    goods_id       bigint       default 0    not null comment '商品ID',
    batch_num      varchar(18)  default ''   not null comment '批次号',
    supplier_id    bigint       default 0    not null comment '供应商ID',
    purchase_price double(9, 2) default 0.00 not null comment '采购价',
    sales_price    double(9, 2) default 0.00 not null comment '销售价',
    push_money     double(9, 2) default 0.00 not null comment '销售提成',
    goods_num      int          default 1    not null comment '货物数量',
    user_id        bigint       default 0    not null comment '进货人ID',
    created_at     timestamp                 null,
    updated_at     timestamp                 null
)
    comment '库存表' collate = utf8mb4_unicode_ci;

INSERT INTO inventories (id, goods_id, batch_num, supplier_id, purchase_price, sales_price, push_money, goods_num, user_id, created_at, updated_at) VALUES (3, 1, '202010141044564336', 4, 101.22, 150, 20, 20, 5, '2020-10-14 10:45:31', '2020-10-14 10:45:31');
INSERT INTO inventories (id, goods_id, batch_num, supplier_id, purchase_price, sales_price, push_money, goods_num, user_id, created_at, updated_at) VALUES (4, 2, '202010141045495221', 3, 98.2, 120, 12, 10, 5, '2020-10-14 10:46:13', '2020-10-14 10:46:13');
INSERT INTO inventories (id, goods_id, batch_num, supplier_id, purchase_price, sales_price, push_money, goods_num, user_id, created_at, updated_at) VALUES (5, 1, '202010141046228263', 3, 99, 140, 13, 100, 5, '2020-10-14 10:46:48', '2020-10-14 10:46:48');
INSERT INTO inventories (id, goods_id, batch_num, supplier_id, purchase_price, sales_price, push_money, goods_num, user_id, created_at, updated_at) VALUES (6, 1, '202010141046556889', 4, 101.55, 160, 18, 130, 5, '2020-10-14 10:47:26', '2020-10-14 10:47:26');

出库表 out_storages

create table out_storages
(
    id           bigint unsigned auto_increment
        primary key,
    inventory_id bigint       default 0    not null comment '货物库存ID',
    num          int          default 1    not null comment '出库数量',
    price        double(9, 2) default 0.00 not null comment '售价',
    user_id      bigint       default 0    not null comment '销售人ID',
    created_at   timestamp                 null,
    updated_at   timestamp                 null
)
    comment '货物出库表' collate = utf8mb4_unicode_ci;

create index inventory_id_index
    on out_storages (inventory_id);

INSERT INTO out_storages (id, inventory_id, num, price, user_id, created_at, updated_at) VALUES (1, 3, 5, 100, 7, null, null);
INSERT INTO out_storages (id, inventory_id, num, price, user_id, created_at, updated_at) VALUES (3, 3, 15, 120, 7, null, null);
INSERT INTO out_storages (id, inventory_id, num, price, user_id, created_at, updated_at) VALUES (4, 5, 10, 120, 7, null, null);
INSERT INTO out_storages (id, inventory_id, num, price, user_id, created_at, updated_at) VALUES (5, 5, 90, 20, 7, null, null);

目的
查询出库存为0的记录
例:

A商品在库存表中按 批次 存在3条记录,其中两个批次的货物已经出库清零了。用户在列表页查询库存为0的商品,这时查询出来的结果想要的是A商品清零的两个批次的记录。

我写了一个Sql满足了需求,但是感觉不美观,而且用laravel ORM 也没有攒出来^_^! 大家看看还能否做优化?Sql如下:

select *  from inventories where goods_num - (select sum(num) from out_storages where inventory_id = inventories.id group by inventory_id) < 1;

欢迎大家指导,谢谢

《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
最佳答案

加字段吧,出库的时候更新字段,你这样出库的sql不是更难写么

4年前 评论
讨论数量: 5

能否在商品表goods内冗余一个剩余库存量的字段呢,感觉这样比较好查询

4年前 评论

加字段吧,出库的时候更新字段,你这样出库的sql不是更难写么

4年前 评论

@jmluang 我一开始想加个字段了,但是考虑到出库频繁,为了维护一个字段开销是不是有点大了

4年前 评论

@konghou 我也纠结是不是要维护一个字段

4年前 评论
Inventory::query()
         ->where(function (\Illuminate\Database\Query\Builder $builder) {
                $builder->selectRaw('sum(num) as num_sum')
                    ->from('out_storages')
                    ->whereColumn('inventory_id', 'inventories.id');
              },
              DB::raw('`id`')
            )
         ->get();
4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!