帮助MYSQL查询聚合计数(替代三个子查询)

时间:2011-08-28 05:00:43

标签: mysql aggregation

我正在尝试从年份的统计数据表和组中输出总内容视图...我的统计数据表是INNODB并且有8M行且正在增长...

该表基本上是ID,DATE,MAKE,IP,REFERRER(id,date,make上的索引)

每个条目都有一个自动递增的ID,输入日期YYYY-MM-DD HH:MM:SS,产品类似'sony','panasonic'等......

我正在尝试制作一个不会杀死我的服务器的查询,它总结了每年的总内容视图,并按照从最常见到最少查看的顺序显示它们(2011年的2011年)以便我可以使用这个数据填充了JS图表,比较了今年和过去几年。我可以通过多个查询来执行此操作并在PHP中使用数组,但我认为应该有一种方法可以在一个查询中获取它,但是如果我能弄明白的话,那该死的。

有什么想法吗?另外,我最好做三个独立的查询并用PHP处理结果,或者我可以将它变成一个更有效的MYSQL查询。

我希望看到的输出(虽然我似乎无法做到这一点),只是

MAKE           2009Total   2010Total 2011Total
----           ---------   --------- ---------
Panasonic      800         2345      3456
Sony           998         5346      2956
JVC            1300        1234      1944           

假设从2009年到现在我的表中都有数据,我需要我的数组每个包含一行......

任何帮助将不胜感激...我很惊讶这样的结果有多快从分析工具回来,我的4x四核XEON RAID mysql服务器需要大约75秒...这个统计表没有被写入但是每天一次转储前一天的统计数据所以我不确定为什么我的3个sep查询是如此之慢......因此我的问题......也许一个查询不会更快?

无论如何,任何帮助都会受到赞赏,并欢迎从通用视图统计表加速统计查询的意见!

2 个答案:

答案 0 :(得分:1)

我做了一个观察。您的查询按年要求。你应该做两件事:

  1. 存储年份
  2. 创建更好的索引(产品,年份)
  3. 以下是你可以这样做的方式:

    CREATE TABLE stats_entry_new LIKE stats_entry;
    ALTER TABLE stats_entry_new ADD COLUMN entryyear SMALLINT NOT NULL AFTER date;
    ALTER TABLE stats_entry_new ADD INDEX product_year_ndx (product,year);
    ALTER TABLE stats_entry_new DISABLE KEYS;
    INSERT INTO stats_entry_new
    SELECT ID, DATE,YEAR(date),product,IP,REFERRER FROM state_entry;
    ALTER TABLE stats_entry_new ENABLE KEYS;
    ALTER TABLE stats_entry RENAME stats_entry_old;
    ALTER TABLE stats_entry_new RENAME stats_entry;
    

    现在查询如下:

    SELECT A.product,B.cnt "2009Total",C.cnt "2010Total",D.cnt "2011Total"
    FROM
    (SELECT DISTINCT product FROM stats_entry) A
    INNER JOIN 
    (SELECT product,COUNT(1) cnt FROM stats_entry WHERE entryyear=2009 GROUP BY product) B
    USING (product)
    (SELECT product,COUNT(1) cnt FROM stats_entry WHERE entryyear=2010 GROUP BY product) C
    USING (product)
    (SELECT product,COUNT(1) cnt FROM stats_entry WHERE entryyear=2011 GROUP BY product) D
    USING (product);
    

    现在公平地说,如果你不想在表格中添加一年,那么你仍然需要制作一个索引

    ALTER TABLE stats_entry ADD INDEX product_date_ndx (product,date);
    

    您的查询现在看起来像这样

    SELECT A.product,B.cnt "2009Total",C.cnt "2010Total",D.cnt "2011Total"
    FROM
    (SELECT DISTINCT product FROM stats_entry) A
    INNER JOIN 
    (SELECT product,COUNT(1) cnt FROM stats_entry
    WHERE date >= '2009-01-01 00:00:00'
    AND date <= '2009-12-31 23:59:59'
    GROUP BY product) B
    USING (product)
    (SELECT product,COUNT(1) cnt FROM stats_entry
    WHERE date >= '2010-01-01 00:00:00'
    AND date <= '2010-12-31 23:59:59'
    GROUP BY product) C
    USING (product)
    (SELECT product,COUNT(1) cnt FROM stats_entry
    WHERE date >= '2011-01-01 00:00:00'
    AND date <= '2011-12-31 23:59:59'
    GROUP BY product) D
    USING (product);
    

    试一试!!!

答案 1 :(得分:0)

SELECT make,year(date) as year,sum(views) 
FROM `stats ` 
group by make,year

o / p:

MAKE         year        sum
-------       -------    ---------  
Panasonic    2009        800     
Panasonic    2010        2345    
Panasonic    2011        3456

...

你可以稍后在php端进行分离。

select make ,group_concat(cast(yr_views as char)) as year_views
from (SELECT make,concat(year(date),':',sum(views)) as yr_views
FROM `stats` 
group by make,year(date))as make_views
group by make

O / P:

make             year_views
------         ---------------
panasonic   2009:800,2010:2345,2011:3456
...

稍后,在PHP级别爆炸&amp;得到了结果。