首先要说明一点,这是一个非常复杂的数据结构,对于精通mysql的人来说,理解很好理解.但是可能还有更大的速度提升空间.

这种涉及到6个表的查询,使用一句话来完成,7000多商品,总数据量应该是十万级,200毫秒应该还是可以接受了.毕竟使用的rds性能也不是特别好.

而且多个表在一句话里面来进行查询的话,有助于练习mysql思维而且灵动性比较好.视图多是很方便写语句,但是效率有时候非常低.

本文主要着重于解决如下问题,都是属于个人笔记

1 如何用一条语句执行多个表的联合查询并提升效率

2 多个表联合查询的时候,sum函数数字很大不准确的问题解决,比如表a,b,c 都有字段需要进行sum统计的错误结果解决

3 left join 的使用

 

用到的表有:

1.商品信息表

2.出库明细表

3.出库单表

4.入库明细表

5.入库单表

6.每次盘点情况的信息表

商品媒体信息表

 

解决如下需求:

1 一条语句罗列并统计出来:itemid,name,imgurl,incount,outcount,hascount,outpopolaration

分别意思为 商品编号,名称,图片url,本阶段总出库数量,本阶段总出库数量,本阶段出库商品的流行度

信息分别来源于:

商品表,商品表,商品媒体信息表,入库明细表,出库明细表,临时创建的表,出库信息表

其中有没展示数据的表为:盘点信息表,入库单表,出库单表.   这三个表都是做关联用的

另外上面提到一个 临时创建的表   有hascount 字段  其实不是表,而是直接用两个列的减法来做的.

先贴出来最终的查询语句

SELECT
	a.itemid,
	a.`name`,
	d.filepath AS imgurl,
	c.incount,
	b.outcount,
	(c.incount - b.outcount) AS hascount,
	b.outpopularation
FROM
	iteminfo a
LEFT JOIN (
	(
		SELECT
			outstockbilldetial.itemid,
			sum(outstockbilldetial.count) AS outcount,
			ifnull(count(*) ,- 1) AS outpopularation
		FROM
			outstockbilldetial,
			outstockbill
		WHERE
			outstockbill.Time > (
				SELECT
					max(FinishTime)
				FROM
					ventorycheckbatchinfo
			)
		AND outstockbill.Canceled = 0
		AND outstockbill.OutStockBillId = outstockbilldetial.OutStockBillId
		GROUP BY
			itemid
	) AS b
	INNER JOIN (
		SELECT
			instockbilldetial.itemid,
			ifnull(
				sum(instockbilldetial.count),
				0
			) AS incount
		FROM
			instockbilldetial,
			instockbill
		WHERE
			instockbill.Time > (
				SELECT
					max(FinishTime)
				FROM
					ventorycheckbatchinfo
			)
		AND instockbill.Canceled = 0
		AND instockbill.InStockBillId = instockbilldetial.InStockBillId
		GROUP BY
			itemid
	) AS c ON b.itemid = c.itemid
) ON a.itemid = b.itemid
LEFT JOIN itemmediainfo AS d ON a.itemid = d.itemid
GROUP BY
	a.itemid
ORDER BY
	hascount ASC

 

 

再贴出来最后的查询结果 

MySQL字段过多错误 mysql字段太多_Time

 

然后 我们发现 查询的数据中,有的是有入库没有出库的,那么连入库记录都看不到了,也自然看不到实际的库存了.这怎么办?

 把入库记录挪到前面去. 这样就能保证商品和入库记录都有,然后虽然有的商品入库了没出库,那也离统计出来更进一步了

SELECT
	a.itemid,
	a.`name`,
	d.filepath AS imgurl,
	c.incount,
	b.outcount,
	(c.incount - b.outcount) AS hascount,
	b.outpopularation
FROM
	iteminfo a
LEFT JOIN (
		SELECT
			instockbilldetial.itemid,
			ifnull(
				sum(instockbilldetial.count),
				0
			) AS incount
		FROM
			instockbilldetial,
			instockbill
		WHERE
			instockbill.Time > (
				SELECT
					max(FinishTime)
				FROM
					ventorycheckbatchinfo
			)
		AND instockbill.Canceled = 0
		AND instockbill.InStockBillId = instockbilldetial.InStockBillId
		GROUP BY
			itemid
	) AS c ON a.itemid = c.itemid

LEFT JOIN (
	(
		SELECT
			outstockbilldetial.itemid,
			ifnull(sum(outstockbilldetial.count),-1000) AS outcount,
			ifnull(count(*),-1000) AS outpopularation
		FROM
			outstockbilldetial,
			outstockbill
		WHERE
			outstockbill.Time > (
				SELECT
					max(FinishTime)
				FROM
					ventorycheckbatchinfo
			)
		AND outstockbill.Canceled = 0
		AND outstockbill.OutStockBillId = outstockbilldetial.OutStockBillId
		GROUP BY
			itemid
	) AS b) on b.itemid = c.itemid
LEFT JOIN itemmediainfo AS d ON a.itemid = d.itemid

GROUP BY
	a.itemid
ORDER BY
	outpopularation ASC

再次进行改善以后,出库如果是没有没有记录的话,也不影响hascount也就是剩余库存的统计

另外 popularation 字段,如果是没有出库过的,就标记为-1

总记录条数 7820条 改善后  0.23秒

 

 

然后如果我们查询商品有库存但是没有出库记录的  

我们加一下where查询条件即可

where 
 (
         c.incount - ifnull(b.outcount, 0)
     ) >0

然后我们再根据拥有库存的多少,来排序一下滞销品

SELECT
	a.itemid,
	a.`name`,
	d.filepath AS imgurl,
	c.incount,
	b.outcount,
	(
		c.incount - ifnull(b.outcount, 0)
	) AS hascount,
	ifnull(b.outpopularation, - 1) AS popularation
FROM
	iteminfo a
LEFT JOIN (
	SELECT
		instockbilldetial.itemid,
		ifnull(
			sum(instockbilldetial.count),
			0
		) AS incount
	FROM
		instockbilldetial,
		instockbill
	WHERE
		instockbill.Time > (
			SELECT
				max(FinishTime)
			FROM
				ventorycheckbatchinfo
		)
	AND instockbill.Canceled = 0
	AND instockbill.InStockBillId = instockbilldetial.InStockBillId
	GROUP BY
		itemid
) AS c ON a.itemid = c.itemid
LEFT JOIN (
	(
		SELECT
			outstockbilldetial.itemid,
			ifnull(
				sum(outstockbilldetial.count) ,- 1000
			) AS outcount,
			ifnull(count(*) ,- 1000) AS outpopularation
		FROM
			outstockbilldetial,
			outstockbill
		WHERE
			outstockbill.Time > (
				SELECT
					max(FinishTime)
				FROM
					ventorycheckbatchinfo
			)
		AND outstockbill.Canceled = 0
		AND outstockbill.OutStockBillId = outstockbilldetial.OutStockBillId
		GROUP BY
			itemid
	) AS b
) ON b.itemid = c.itemid
LEFT JOIN itemmediainfo AS d ON a.itemid = d.itemid
WHERE
	(
		c.incount - ifnull(b.outcount, 0)
	) > 0
AND outpopularation IS NULL
GROUP BY
	a.itemid
ORDER BY
	hascount DESC

如果查询滞销的40条商品 加上 limit 40就可以了