mysql在单个查询中比较销售/购买
Posted
技术标签:
【中文标题】mysql在单个查询中比较销售/购买【英文标题】:mysql compare sales/purchase in single query 【发布时间】:2014-12-12 20:39:03 【问题描述】:我们有一个专有的销售系统,我们已经使用了一段时间。 最近我们添加了“购买”部分,以便我们可以比较匹配产品的平均购买/销售价格以及查看库存位置。
在 mysql 中,我有 2 个表:tblPurchases 和 tblSalesDetail。
每个都有 productID、数量、价格和运费字段(所有数字)。
我想查询每个产品 ID:
[产品ID] [总购买数量] [平均购买价格] [平均采购运费] [总销售数量] [平均销售价格] [平均 销售运费]
我当前的sql语句是这样的
select
tblPurchases.productID,
tblSalesDetail.productNo,
sum(tblPurchases.quantity) as pQuantity,
avg(tblPurchases.price) as pPrice,
avg(tblPurchases.freight) as pFreight,
sum(tblSalesDetail.quantity) as sQuantity,
format(avg(tblSalesDetail.unitPrice),2) as sPrice,
format(avg(tblSalesDetail.freight),2) as sFreight
from
tblPurchases
left join tblSalesDetail
on tblPurchases.productID=tblSalesDetail.productNo
group by tblPurchases.productID
但它只有在双方都有匹配的产品 ID 时才能正常工作。 我希望它还显示没有匹配购买产品 ID 的产品 ID 的销售额。
单个查询可以实现吗?
=============
已编辑
新查询如下所示
select
ps.productID,
ps.productNo,
sum(ps.pQuantity) as pQuantity,
avg(ps.pPrice) as pPrice,
avg(ps.pFreight) as pFreight,
sum(sQuantity) as sQuantity,
avg(sPrice) as sPrice,
avg(sFreight) as sFreight
from (
(select productID,
null as productNo,
quantity as pQuantity,
price as pPrice,
freight as pFreight,
NULL as sQuantity,
NULL as sPrice,
NULL as sFreight
from tblPurchases)
union all
(select null as productID,
productNo,
NULL as pQuantity,
NULL as pPrice,
null as pFreight,
quantity as sQuantity,
unitPrice as sPrice,
freight as sFreight
from tblSalesDetail
)
) as ps
group by ps.productID
但是我得到了 2 行,所有无与伦比的销售额都被平均放在一行上。
如果我运行每个单独的查询,例如
select null as productID,
productNo,
NULL as pQuantity,
NULL as pPrice,
null as pFreight,
quantity as sQuantity,
unitPrice as sPrice,
freight as sFreight
from tblSalesDetail
我得到了我期望得到的结果(大约 5000 行)。
================
已解决
select
*
from (
(select tblPurchases.productID as pProduct,
tblSalesDetail.productNo as sProduct,
sum(tblPurchases.quantity) as pQuantity,
avg(tblPurchases.price) as pPrice,
avg(tblPurchases.freight) as pFreight,
tblSalesDetail.quantity as sQuantity,
tblSalesDetail.unitPrice as sPrice,
tblSalesDetail.freight as sFreight
from tblPurchases
left join tblSalesDetail on tblPurchases.productID=tblSalesDetail.productNo
group by tblPurchases.productID)
union all
(select tblPurchases.productID as pProduct,
tblSalesDetail.productNo,
tblPurchases.quantity as pQuantity,
tblPurchases.price as pPrice,
tblPurchases.freight as pFreight,
sum(tblSalesDetail.quantity) as sQuantity,
avg(tblSalesDetail.unitPrice) as sPrice,
avg(tblSalesDetail.freight) as sFreight
from tblSalesDetail
left join tblPurchases on tblPurchases.productID=tblSalesDetail.productNo
group by tblSalesDetail.productNo)
) as ps
【问题讨论】:
【参考方案1】:这是因为您正在执行 LEFT OUTER JOIN
TO tblSalesDetail
,它给出了双方的所有匹配实例,以及没有销售详细信息的购买实例(而不是相反)。两种选择:
给我所有的销售细节,但只给我匹配的购买
SELECT Purchases.productID AS productID
,Sales.productNo AS productNo
,SUM(Purchases.quantity) AS pQuantity
,AVG(Purchases.price) AS pPrice
,AVG(Purchases.freight) AS pFreight
,SUM(Sales.quantity) AS sQuantity
,FORMAT(AVG(Sales.unitPrice),2) AS sPrice
,FORMAT(AVG(Sales.freight),2) AS sFreight
FROM tblSalesDetail AS Sales
LEFT OUTER JOIN tblPurchases AS Purchases
ON Purchases.productID = Sales.productNo
GROUP BY Purchases.productID
只需切换表,tblSalesDetail
即可成为驱动程序。
给我所有销售细节和所有购买,无论匹配如何
注意:编辑因为 MySQL 不支持FULL OUTER JOIN
s。
SELECT productID
,productNo
,SUM(pQuantity) AS pQuantity
,AVG(pPrice) AS pPrice
,AVG(pFreight) AS pFreight
,SUM(sQuantity) AS sQuantity
,FORMAT(AVG(sPrice),2) AS sPrice
,FORMAT(AVG(sFreight),2) AS sFreight
FROM (
SELECT Purchases.productID AS productID
,Sales.productNo AS productNo
,Purchases.quantity AS pQuantity
,Purchases.price AS pPrice
,Purchases.freight AS pFreight
,Sales.quantity AS sQuantity
,Sales.unitPrice AS sPrice
,Sales.freight AS sFreight
FROM tblPurchases AS Purchases
LEFT OUTER JOIN tblSalesDetail AS Sales
ON Purchases.productID = Sales.productNo
UNION
SELECT Purchases.productID AS productID
,Sales.productNo AS productNo
,Purchases.quantity AS pQuantity
,Purchases.price AS pPrice
,Purchases.freight AS pFreight
,Sales.quantity AS sQuantity
,Sales.unitPrice AS sPrice
,Sales.freight AS sFreight
FROM tblSalesDetail AS Sales
LEFT OUTER JOIN tblPurchases AS Purchases
ON Purchases.productID = Sales.productNo
) AS FullOuterJoin
GROUP BY productID
,productNo
FULL OUTER JOIN
(通过 UNION ALL
与两个 LEFT OUTER JOIN
S 完成,然后组合在一起)将在匹配存在时关联匹配,但提供两个表中的所有现有记录,即使一侧与另一侧不匹配,或者反之亦然。
希望这会有所帮助。
【讨论】:
谢谢。这给了我一个错误:您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,以在第 12 行 State: 37000 的 'outer join tblSalesDetail on tblPurchases.productID=tblSalesDetail.productNo gr' 附近使用正确的语法;原生:1064;来源:[MySQL][ODBC 5.2(a) 驱动程序][mysqld-5.5.39-log] 啊该死的,我很少需要FULL OUTER JOIN
id,忘记了它是 MySQL 不支持的少数 ANSI 语法之一。我已经更新了我的第二个示例以使用 UNION
解决方法。
谢谢。那更近了。它现在给了我 2 行而不是 1 行。看起来它正在做的是给我与以前相同的行,再加上另一行,其中包含所有其余销售额(没有购买匹配)的平均值和总和,而不是按 Sales.productNo 对它们进行分组和列出
对不起,我的回答很匆忙,忘记在顶层而不是子查询上进行聚合。我已经更新了我的答案以使用 UNION
而不是 UNION ALL
(您可以将其作为三层查询,但只有在处理数百万条记录时才真正需要)并进行更简单的顶层聚合。希望这会有所帮助。【参考方案2】:
问题是您需要full outer join
,但 MySQL 不支持它。但是,您可以使用 union all
和聚合执行基本相同的操作。这基本上就是查询的样子:
select ps.productID,
sum(pquantity) as pQuantity, avg(pPrice) as pPrice, avg(pFreight) as pFreight,
sum(squantity) as sQuantity, avg(sPrice) as sPrice, avg(sFreight) as sFreight
from ((select productid,
quantity as pQuantity, price as pPrice, freight as pFreight,
NULL as sQuantity, NULL as sPrice, NULL as sfreight
from tblPurchases
) union all
(select productno, NULL as pQuantity
quantity as sQuantity, price as sPrice, freight as sFreight,
from tblSalesDetail
)
) ps
group by ps.productID;
【讨论】:
谢谢。好吧,这并没有错,但我只得到 2 行。看起来它将(平均/求和)所有无与伦比的销售额放在一行中。如果我分别运行我们尝试 UNION 的 2 个 sql 语句,它们会按预期工作.... 哦,我明白了。两张桌子上有不同的键,一张是productid
,另一张是productno
。以上解决了这个问题。
是的,这两个字段是相同的,它们应该命名相同,但我继承了它。谢谢!以上是关于mysql在单个查询中比较销售/购买的主要内容,如果未能解决你的问题,请参考以下文章
[LeetCode]1083. 销售分析 II(Mysql,having+if)