我有一个包含数千个订单的在线商店,我正在写一些查询,以确定每个供应商(品牌)在网站上赚了多少钱。我有以下查询,一个是所选年份的每个月:
$filterJan = "$filterYear-01";
$queryJan = "SELECT price, quantity FROM order_items WHERE productID='$productID' AND timestamp LIKE '%$filterJan%' LIMIT 10000";
$suppliersQueryFilter = mysql_query($queryJan, $connection) or die(mysql_error());
while($rowF = mysql_fetch_assoc($suppliersQueryFilter)) {
$price = $rowF["price"]*$rowF["quantity"];
$totalJan = $totalJan+$price;
}
**等等每个月**
加载需要很长时间(我们至少谈论超过60秒)并且我知道它在任何形状或形式上都没有效率。对于每个月,这些查询都会搜索数千条记录。有没有更有效的方式或写这个:
a)将代码量减少到1个查询 b)提高装载时间的效率
$ filterYear包含一年,如2009年。
所以这个查询的作用是它选择每个月为选定年份(分配给$ filterYear)赚了多少钱。所以它产生的结果是1月,2月,3月的表...每个月有多少钱,所以2345英镑,2101英镑等......
答案 0 :(得分:2)
您应该将时间戳存储为实际的mysql日期时间值,这会产生类似
的内容GROUP BY YEAR(timestamp), MONTH(timestamp)
WHERE timestamp BETWEEN $initialtime AND $finaltime
很可能。这样就可以将多个基本相同的重复查询减少到一个查询。
您可以为此使用派生值,但它的效率低于使用本机日期时间字段:
GROUP BY SUBSTR(timestamp, 0, 4), SUBSTR(timestamp, 6,2)
答案 1 :(得分:1)
为了获得最佳性能,您需要向数据库提交类似的查询:
SELECT DATE_FORMAT(i.timestamp,'%Y-%m') AS `month`
, SUM(i.price*i.qty) AS `total`
FROM order_items i
WHERE i.productID = 'foo'
AND i.timestamp >= '2013-01-01'
AND i.timestamp < '2013-01-01' + INTERVAL 12 MONTH
GROUP
BY DATE_FORMAT(i.timestamp,'%Y-%m')
(这假设timestamp
列是MySQL数据类型TIMESTAMP
,DATETIME
或DATE
)
使用已弃用的mysql_接口,您希望使用mysql_real_escape_string
函数来避免SQL注入漏洞。 (更好的选择是使用mysqli或PDO接口,并使用带有绑定占位符的预准备语句。)
我们希望时间戳上的谓词位于BARE列上,因此MySQL可以使用适用于范围扫描操作的合适索引,而不需要对表中的每一行进行完全扫描。
我们还想利用服务器的强大功能快速派生一个总数,然后只返回总数,而不是检索每个翻转行,并单独处理每个行(RBAR =通过痛苦排行)
GROUP BY
子句和SUM()
聚合函数是根据此结果量身定制的。
使用mysql_接口,查询看起来像这样:
$querytext = "
SELECT DATE_FORMAT(i.timestamp,'%Y-%m') AS `month`
, SUM(i.price*i.qty) AS `total`
FROM order_items i
WHERE i.productID = '" . mysql_real_escape_string($thisProductID) . "'
AND i.timestamp >= '" . mysql_real_escape_string($filterYear) . "-01-01'
AND i.timestamp < '" . mysql_real_escape_string($filterYear) . "-01-01' +
INTERVAL 12 MONTH
GROUP BY DATE_FORMAT(i.timestamp,'%Y-%m')";
# for debugging
#echo $querytext;