目录
前言
在一个项目中有两张表,一张是商品码表,一张是记录出库单明细的出库记录表,记录表中有一个字段保存了以逗号隔开的商品码表的id字符串,需要根据出库明细id查找到对应出库的商品码。
表结构
goods_detail 商品码表结构
sql
CREATE TABLE `goods_detail` (
`id` bigint(20) NOT NULL COMMENT '主键',
`goods_id` bigint(20) NOT NULL COMMENT '商品id',
`bar_code` varchar(20) DEFAULT NULL COMMENT '箱码',
`bottle_code` varchar(20) DEFAULT NULL COMMENT '瓶码'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='商品码表';
out_goods_record 出库记录表结构
sql
CREATE TABLE `out_goods_record` (
`id` bigint(20) NOT NULL COMMENT 'ID',
`order_detail_id` bigint(20) NOT NULL COMMENT '出库单明细id',
`goods_detail_id` longtext COMMENT '商品码id,多个用'',''分隔'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='出库记录';
sql语句
- 使用查询函数FIND_IN_SET和函数GROUP_CONCAT
sql
SELECT
id,
bar_code,
bottle_code
FROM
goods_detail
WHERE
FIND_IN_SET(
id,(
SELECT
GROUP_CONCAT( goods_detail_id )
FROM
out_good_record
WHERE
del_flag = '0'
AND order_detail_id = 1734492741712220161
GROUP BY
order_detail_id
))>0;
该sql查询效率非常低,需要147秒,前端会提示请求接口超时,不推荐。
- 将逗号隔开的商品码id转成多行再查询
将逗号隔开的商品码id转成多行的sql
sql
SELECT
substring_index( substring_index( r.goods_detail_id, ',', s.id + 1 ), ',',- 1 ) AS goods_detail_id
FROM
out_good_record r
CROSS JOIN auto_add_seq s ON s.id <= LENGTH( r.goods_detail_id ) - LENGTH(
REPLACE ( r.goods_detail_id, ',', '' ))
WHERE
r.order_detail_id = 1734492741712220161
auto_add_seq 这张表为自定义表,参考 mysql中字符串截取与拆分链接中的 二、分割成多行
- 使用EXISTS
sql
SELECT
id,
bar_code,
bottle_code
FROM
goods_detail d
WHERE
EXISTS (
SELECT
1
FROM
(
SELECT
substring_index( substring_index( r.goods_detail_id, ',', s.id + 1 ), ',',- 1 ) AS goods_detail_id
FROM
out_good_record r
CROSS JOIN incr_sequence s ON s.id <= LENGTH( r.goods_detail_id ) - LENGTH(
REPLACE ( r.goods_detail_id, ',', '' ))
WHERE
r.order_detail_id = 1734492741712220161
) t
WHERE
t.goods_detail_id = d.id
);
由于数据量太大,使用EXISTS花费的时间太多了,EXISTS比较适合内部是大表的情况,不推荐使用
- 使用IN查询
sql
SELECT
id,
bar_code,
bottle_code
FROM
goods_detail d
WHERE
d.id IN (
SELECT
substring_index( substring_index( r.goods_detail_id, ',', s.id + 1 ), ',',- 1 ) AS goods_detail_id
FROM
out_good_record r
CROSS JOIN incr_sequence s ON s.id < LENGTH( r.goods_detail_id ) - LENGTH( REPLACE ( r.goods_detail_id, ',', '' ) + 1 )
WHERE
r.order_detail_id = 1734492741712220161
);
使用IN查询,要效率要高多了
- 关联查询
sql
SELECT
id,
bar_code,
bottle_code
FROM
goods_detail d,
(
SELECT
substring_index( substring_index( r.goods_detail_id, ',', s.id + 1 ), ',',- 1 ) AS goods_detail_id
FROM
out_good_record r
CROSS JOIN incr_sequence s ON s.id <= LENGTH( r.goods_detail_id ) - LENGTH(
REPLACE ( r.goods_detail_id, ',', '' ))
WHERE
r.order_detail_id = 1734492741712220161
) t
WHERE
d.id = t.goods_detail_id
关联查询效率最高,推荐使用