【问题标题】:Optimize my two queries in to one将我的两个查询优化为一个
【发布时间】:2012-11-19 11:54:26
【问题描述】:

我有两张表,一张用于跟踪聊天统计信息,一张用于跟踪邮件统计信息。

我当前的查询如下所示:

SELECT COUNT(id) as chat_amount, DATE_FORMAT(timestamp, '%b %e') as period FROM tblChats WHERE timestamp BETWEEN '{$start}' AND '{$end}' AND UserID = 0 GROUP BY DAY(timestamp) DESC, MONTH(timestamp) DESC, YEAR(timestamp) DESC

SELECT COUNT(id) as mail_amount, DATE_FORMAT(timestamp, '%b %e') as period FROM tblMails WHERE timestamp BETWEEN '{$start}' AND '{$end}' AND UserID = 0 GROUP BY DAY(timestamp) DESC, MONTH(timestamp) DESC, YEAR(timestamp) DESC

我想将这两个查询合并为一个,以便返回的数据如下所示:

Array ( 
[0] => Array ( 
    [period] => 2012-11-09 
    [chat_amount] => 1500 
    [mail_amount] => 100 
) 
[1] => Array ( 
    [period] => 2012-11-08 
    [chat_amount] => 500 
    [mail_amount] => 350 
) 
[2] => Array ( 
    [period] => 2012-11-07 
    [chat_amount] => 2000 
    [mail_amount] => 1300 
) 
[3] => Array ( 
    [period] => 2012-11-06 
    [chat_amount] => 1000 
    [mail_amount] => 970 
) 

)

我怎样才能实现这样的目标?提前谢谢你。

【问题讨论】:

    标签: mysql multi-query


    【解决方案1】:

    虽然 Saharsh 的答案似乎以您想要的格式为您提供了结果 - 这是一个非常昂贵的查询。

    由于您将预期输出引用为序列化的 PHP 数组,这意味着您正在使用 PHP 来处理数据。一种更有效的方法是使用以下查询,然后将数据合并到 PHP 数组中:

     SELECT rtype, DATE_FORMAT(iperiod, '%b %e') AS period, amount
     FROM
     (SELECT 'chat' AS rtype,
       COUNT(id) as amount, 
       DATE(timestamp) as iperiod 
       FROM tblChats 
       WHERE timestamp BETWEEN '{$start}' AND '{$end}' 
       AND UserID = 0 
       GROUP BY DATE(timestamp)
     UNION
       SELECT 'mail' as rtype, 
       COUNT(id) as mail_amount, 
       DATE(timestamp) as iperiod 
       FROM tblMails 
       WHERE timestamp BETWEEN '{$start}' AND '{$end}' 
       AND UserID = 0 
     GROUP BY DATE(timestamp)) ilv
     ORDER BY period DESC;
    

    顺便说一句:DATE_FORMAT(timestamp, '%b %e') 不会产生 '2012-11-09',DESC 修饰符是否适用于 GROUP BY 表达式?

    【讨论】:

    • 我跟着你。 Saharsh 的查询确实为我提供了预期的输出,但我真的很喜欢你的方法。
    • symcbean,是的,DESC 修饰符确实适用于 GROUP BY 表达式。
    【解决方案2】:

    试试这个:

    SELECT A.period, chat_amount, mail_amount FROM (
    (SELECT COUNT(id) AS chat_amount, DATE_FORMAT(TIMESTAMP, '%b %e') AS period FROM tblChats WHERE TIMESTAMP BETWEEN '{$start}' AND '{$end}' AND UserID = 0 GROUP BY DAY(TIMESTAMP) DESC, MONTH(TIMESTAMP) DESC, YEAR(TIMESTAMP) DESC) AS A 
    LEFT JOIN 
    (SELECT COUNT(id) AS mail_amount, DATE_FORMAT(TIMESTAMP, '%b %e') AS period FROM tblChats WHERE TIMESTAMP BETWEEN '{$start}' AND '{$end}' AND UserID = 0 GROUP BY DAY(TIMESTAMP) DESC, MONTH(TIMESTAMP) DESC, YEAR(TIMESTAMP) DESC) AS B ON A.period = B.period)
    UNION 
    SELECT A.period, chat_amount, mail_amount FROM (
    (SELECT COUNT(id) AS chat_amount, DATE_FORMAT(TIMESTAMP, '%b %e') AS period FROM tblChats WHERE TIMESTAMP BETWEEN '{$start}' AND '{$end}' AND UserID = 0 GROUP BY DAY(TIMESTAMP) DESC, MONTH(TIMESTAMP) DESC, YEAR(TIMESTAMP) DESC) AS A 
    RIGHT JOIN 
    (SELECT COUNT(id) AS mail_amount, DATE_FORMAT(TIMESTAMP, '%b %e') AS period FROM tblChats WHERE TIMESTAMP BETWEEN '{$start}' AND '{$end}' AND UserID = 0 GROUP BY DAY(TIMESTAMP) DESC, MONTH(TIMESTAMP) DESC, YEAR(TIMESTAMP) DESC) AS B ON A.period = B.period)
    

    【讨论】:

    • 几乎成功了。但是,运行查询会在 mail_amount 和 chat_amount 中返回相同的数字。
    • 对不起,我在表名中打错了。像魅力一样工作。非常感谢!
    • 如果这真的适合你,那么接受答案并投票
    猜你喜欢
    • 1970-01-01
    • 2012-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-08
    • 2011-09-18
    • 2018-06-15
    相关资源
    最近更新 更多