[英]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.