PHP和MYSQL查询从多列中提取重复项

时间:2017-03-10 19:48:52

标签: php mysql

我正在论坛上的线程页面记录信息,4天内有近400,000个条目,一个SQL查询使用12秒,如果可能,我需要帮助减少查询运行时间或使用php计算客人查看每个thread_id

我有以下mysql表和列

thread_count

count_id thread_id user_id timestamp ip_address

对于使用此查询的观看次数超过100次的主题,我已经在0.2秒内获得每周统计数据

SELECT thread_id, timestamp, user_id, COUNT(thread_id) AS cnt FROM thread_count GROUP BY thread_id HAVING COUNT( thread_id) >100 AND timestamp > UNIX_TIMESTAMP() - 24 * 3600 * 7 ORDER BY cnt DESC

问题是指我尝试运行此查询以查看有多少来宾视图

$guestcount = SELECT user_id, thread_id, COUNT(user_id) AS cntg FROM thread_count WHERE user_id =0 AND thread_id = ".$array['thread_id']."

在第一个查询的while循环中运行

第二个查询需要12.9秒才能运行

这是来自php代码的while循环,它的vbulletin可能看起来很奇怪

while ($array = $db->fetch_array($threadsql)){

                $thread_title = $db->fetch_array($vbulletin->db->query_read("SELECT title FROM thread WHERE threadid = ".$array['thread_id'].""));

            //  $guestcount = $db->fetch_array($vbulletin->db->query_read("SELECT user_id, thread_id, COUNT(user_id) AS cntg FROM " . TABLE_PREFIX . "thread_count WHERE user_id =0 AND thread_id = ".$array['thread_id'].""));

                $weekly .= '<tr><td><a href="showthread.php?t='.$array['thread_id'].'">'.$array['thread_id'].'</a></td>
                <td>'.$array['cnt'].' </td> <td><a href="showthread.php?t='.$array['thread_id'].'">'.$thread_title[title].'</a></td><td>Username Here</td> <td>'.$guestcount[cntg].'</td> </tr>';               

            }

基本上,客户点击在 user_id 列中存储为 0 ,我确实尝试了这一点而不是使用12秒查询,但它只显示0

foreach($array as $guest){
                if ($array[user_id] = 0 && $thread[thread_id] = $array[thread_id])
                            $guestcount = count($guest);
                }

1 个答案:

答案 0 :(得分:2)

考虑使用SQL解决方案。具体来说,由于您运行两个不同的聚合,因此使用派生表返回 thread_id cnt title cntg 所有字段都在一个查询调用中使用嵌套循环。

此外,遗憾的是,与某些MySQL开发人员一样,您没有运行有效的ANSI SQL,因为GROUP BY必须包含所有非聚合列,因此原始查询应该失败。可能,你关闭了MySQL的ONLY_FULL_GROUP_BY模式(默认情况下从版本5.7.5开始)。下面的查询被调整为完全兼容的SQL,可以移植到其他RDBMS。

SELECT t.thread_id, t.cnt, h.title, g.cntg

FROM
  (SELECT c.thread_id, COUNT(c.thread_id) AS cnt 
   FROM thread_count c
   WHERE c.timestamp > UNIX_TIMESTAMP() - 24 * 3600 * 7 
   GROUP BY c.thread_id 
   HAVING COUNT(c.thread_id) > 100
  ) As t 

INNER JOIN    
 (SELECT c.thread_id, COUNT(c.user_id) AS cntg 
  FROM thread_count c
  WHERE c.user_id=0 
  GROUP BY c.thread_id
 ) As g
ON t.thread_id = g.thread_id

INNER JOIN 
  thread h
ON h.threadid = t.thread_id

ORDER BY t.cnt DESC