[英]Need help on nested loop of queries in php and mysql?
我试图做到这一点:
<?php
$good_customer = 0;
$q = mysql_query("SELECT user FROM users WHERE activated = '1'"); // this gives me about 40k users
while($r = mysql_fetch_assoc($q)){
$money_spent = 0;
$user = $r['user'];
// Do queries on another 20 tables
for($i = 1; $i<=20 ; $i++){
$tbl_name = 'data' . $i;
$q2 = mysql_query("SELECT money_spent FROM $tbl_name WHERE user = '{$user}'");
while($r2 = mysql_fetch_assoc($q2)){
$money_spend += $r2['money_spent'];
}
if($money_spend > 1000000){
$good_customer += 1;
}
}
}
这只是一个例子。 我正在本地主机上测试,对于单用户,它返回速度非常快。 但是,当我尝试使用1000时,它需要永远的时间,甚至没有提到40k用户。
无论如何要优化/改进此代码?
编辑:顺便说一下,其他20个表中的每个表都有〜20-40k记录
编辑2:
好的,放弃“花钱”的想法。 这是我当前的结构:
用户表=>用户是PK
logs_week_1表=>用户为FK。
logs_week_2表=>用户为FK
logs_week_3表=>用户是FK
……将来会有更多的日志表。
我想找到他们在我的网站上花费的“平均时间”,该时间存储在每个日志表中。
你们这么说,每周存储日志是个坏主意吗? 我应该合并成一张桌子吗?
听起来您的模型有问题。 为什么您有20个data
而不是一个week
data
?
那你可以做一个
Select user, Sum( money_spent ) As total_money_spent
From data
Group By user
甚至
Select Count(*) As good_customer_count
From data
Group By user
Having Sum( money_spent ) > 1000000
使用当前的结构,您只能执行以下操作:
Select u.user, d1.money_spent + d2.money_spent + ...
From users u
Join data1 d1 On ( d1.user = u.user )
Join data2 d2 On ( d2.user = u.user )
...
要么
Select Count(*) As good_customer_count
From
( Select d1.money_spent + d2.money_spent + ... As total_money_spent
From data1 d1
Join data1 d1 On ( d1.user = u.user )
Join data2 d2 On ( d2.user = u.user )
...
)
Where total_money_spent > 1000000
这肯定比您当前的解决方案要快。
并且花在页面上的时间应该存储在一个数字字段中。
由于Peter已经给出了一个很好的答案,我将只发布经过适当设计的查询外观(所有日志数据都放在一个表中)
SELECT user, AVG(TIMEDIFF(start_time, end_time)) AS average_time
FROM logs
GROUP BY user
您可以在上述条件中进一步应用条件,以仅获取特定时间段(周,月等)的统计信息,也可以按其他级别分组。
您还可以有效地在同一查询中获得MAX和COUNT(以及标准差和其他聚合函数 )。
当然,请注意使用较大的数据集以获得最佳性能的索引。
编辑:
就像我给彼得+1一样,我注意到他没有提到UNION ALL选项
因此,您可以(这不是最佳选择,并且不与其他人给出的设计问题警告相抵触)
SELECT user, AVG(TIMEDIFF(start_time, end_time)) AS average_time
FROM (
SELECT * FROM log_week_1
UNION ALL
SELECT * FROM log_week_2
UNION ALL
SELECT * FROM log_week_3
...
) U
GROUP BY user
您也可以为此联合创建一个VIEW。
对于40k用户,您要创建1 + 20 * 40k查询。 无论如何这都会很慢。 停止将日志保存在20个表中。 您应该以其他方式设计数据库。 在适当设计的数据库上,所有这些都应通过1个查询来完成
SELECT count(user) as good_customers FROM users JOIN $tbl_name ON users.user = {$tbl_name}.user ON WHERE users.activated = '1' HAVING SUM(money_spent) > 100000.
在最坏的情况下,您还应该使用每个表的1个查询来完成全部操作。
SELECT user, SUM(money_spent) as money_spent FROM users JOIN $tbl_name ON users.user = {$tbl_name}.user ON WHERE users.activated = '1'.
然后将这20个money_spent列加起来即可得到答案。
您应该将在网站上花费的时间存储为数字(以分钟或秒为单位),而不是时间。 然后,您可以计算该值的平均值和总和。 并将您的日志保存在一个表中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.