我现在对MySQL和高效查询有相当的经验,但仍遇到问题......
我有两张表,“发票”和“salesRecords”发票表包含发票的基本概览,销售记录逐行分解有关购买物品的特定信息。
为简单起见,我们假设表格如下:
发票
id | repairCharge | shippingCharge | total
1 | 28.95 | 0 | 30.45
2 | 10.00 | 8.50 | 29.50
//注意;总列包括销售记录中显示的项目
SalesRecords
invNo | itemNo | price | quantity | discount |
1 | 123 | 1.50 | 1 | 0 |
2 | 121 | 6.50 | 1 | 1.5 |
2 | 128 | 5.50 | 1 | 0 |
我想在一个日期期间获得所售商品,人工费和运费的总价值,因此我需要:
JOIN
(左?)SalesRecords表ON invNo和SUM((价格折扣)*数量)我马上写下这个SQL:
SELECT SUM((sr.price-sr.discount)*sr.quantity) as income,
SUM(i.repairCharge) as labour,
SUM(i.shippingCharge) as carriage
FROM invoices i
LEFT JOIN salesRecords sr ON sr.invNo=i.id
WHERE i.dateTime BETWEEN 1431647999 AND 1434360348`
错误
因为,对于包含多个项目行的任何发票,我获得了两个表的多个实例,因此repairCharge
和shippingCharge
值加倍或增加三倍,具体取决于产品线的数量在该发票上购买。
所以,我搞砸了并提出了一个解决方案...但它非常丑陋并且可能效率低下:
SELECT SUM(income) as income,
SUM(labour) as labour,
SUM(carriage) as carriage
FROM (SELECT (SELECT SUM((price-discount)*quantity)
FROM salesRecords
where invno=i.id
GROUP BY invNo) as income,
SUM(i.repairCharge) as labour,
SUM(i.shippingCharge) as carriage
FROM invoices i
WHERE i.dateTime BETWEEN 1434326474 AND 1434361694
GROUP BY id
) totals
任何人都可以建议最简化这种方法并提高效率吗?
答案 0 :(得分:1)
就大多数其他DBMS的易读性和性能而言,我个人只是在子查询中总结销售记录:
SalesRecords
MySQL在子查询上使用中间物化(据我所知),如果这样做,可能会对上述查询产生负面影响,因为它会首先汇总SELECT SUM(COALESCE(i.Income, 0)) AS Income,
SUM(i.repairCharge) AS Labour,
SUM(i.shippingCharge) AS Carriage
FROM ( SELECT i.ID,
i.repairCharge,
i.shippingCharge,
SUM((sr.price - sr.discount) * sr.quantity) AS Income
FROM Invoices AS i
LEFT JOIN SalesRecords AS sr
ON sr.InvNo = i.ID
WHERE i.dateTime BETWEEN 1434326474 AND 1434361694
GROUP BY i.ID, i.repairCharge, i.ShippingCharge
) AS i;
中的所有记录并将结果存储在在发票日期应用过滤器之前的哈希表,所以您的工作版本,但使用JOIN而不是相关子查询可能会表现更好:
Sources
答案 1 :(得分:0)
试试这个:
select sum(labour) as labour,
sum(carriage) as carriage,
sum(income) as income
from( select sum(i.repairCharge) as labour,
sum(i.shippingCharge) as carriage,
coalesce(sum((sr.price - sr.discount) * sr.quantity), 0) as income
from Invoices i
left join SalesRecords sr on i.id = sr.invNo
group by i.id)t