簡體   English   中英

在php和mysql中的嵌套查詢循環上需要幫助嗎?

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM