【问题标题】:Count multiple columns with group by in one query在一个查询中使用 group by 计算多列
【发布时间】:2012-09-23 11:21:14
【问题描述】:

我像这样计算多列中的值:

SELECT COUNT(column1),column1 FROM table GROUP BY column1
SELECT COUNT(column2),column2 FROM table GROUP BY column2
SELECT COUNT(column3),column3 FROM table GROUP BY column3

这例如返回 column1 array(attr1 => 2000, attr2 => 3000...) (每列都有特定的值和少数值)。问题是我的应用程序中的“表”可能是一个带有一些连接和 where 子句的查询,这可能需要 0.1 秒。通过做所有这些计算,“表”每次都会重新计算,这是不必要的。有什么方法可以通过一个查询获取我想要的结果,或者“缓存”生成表的查询?否则我相信非规范化将是这里唯一的解决方案。我想要与上述查询相同的结果。我正在使用 mysql-myisam。

【问题讨论】:

标签: sql database count group-by


【解决方案1】:

SELECT COUNT(col1 OR col2) FROM [table_name] GROUP BY col1,col2;

【讨论】:

  • 请不要只发布代码作为答案,还要解释您的代码的作用以及它如何解决问题的问题。带有解释的答案通常更有帮助、质量更好,并且更有可能吸引投票
【解决方案2】:
    SELECT SUM(Output.count),Output.attr 
FROM
(
    SELECT COUNT(column1  ) AS count,column1 AS attr FROM tab1 GROUP BY column1 
    UNION ALL
    SELECT COUNT(column2) AS count,column2 AS attr FROM tab1 GROUP BY column2
    UNION ALL
    SELECT COUNT(column3) AS count,column3 AS attr FROM tab1 GROUP BY column3) AS Output

    GROUP BY attr 

【讨论】:

    【解决方案3】:
    select tab1.name,
    count(distinct tab2.id) as tab2_record_count
    count(distinct tab3.id) as tab3_record_count
    count(distinct tab4.id) as tab4_record_count
    from tab1
    left join tab2 on tab2.tab1_id = tab1.id
    left join tab3 on tab3.tab1_id = tab1.id
    left join tab4 on tab4.tab1_id = tab1.id
    

    【讨论】:

    • 你能解释一下为什么我们在这里使用 distinct 吗?
    【解决方案4】:

    如果不了解数据的上下文/结构,很难知道如何为您提供帮助,但我相信这可能会对您有所帮助:

    SELECT 
         SUM(CASE WHEN column1 IS NOT NULL THEN 1 ELSE 0 END) AS column1_count
        ,SUM(CASE WHEN column2 IS NOT NULL THEN 1 ELSE 0 END) AS column2_count
        ,SUM(CASE WHEN column3 IS NOT NULL THEN 1 ELSE 0 END) AS column3_count
    FROM table
    

    【讨论】:

    • 这是一个非常有用的查询,尤其是当您需要参与记录的计数时。例如,当我需要向我发送消息的用户数时,我会使用稍微修改过的查询版本。 'SELECT DateSent, SUM(CASE WHEN TotalMessageCount > 1 THEN 1 ELSE 0 END) UserCount'
    • 拯救了我的一天..!!
    【解决方案5】:

    您没有说您使用的是哪个数据库服务器,但如果临时表可用,它们可能是最好的方法。

    // table is a temp table
    select ... into #table ....
    SELECT COUNT(column1),column1 FROM #table GROUP BY column1  
    SELECT COUNT(column2),column2 FROM #table GROUP BY column2  
    SELECT COUNT(column3),column3 FROM #table GROUP BY column3  
    // drop may not be required
    drop table #table
    

    【讨论】:

    • 是的,我可以创建临时表,(mysql 社区服务器),但我认为它不会在性能上有很大的提高,因为创建一个临时表大约需要 1 秒。我确实需要 0.1-0.2 秒的查询,总共需要 1 秒左右。 (你不是说 CREATE TEMPORARY TABLE AS {query} 吗?)
    • 我相信在 Sybase 数据库服务器上,上述语法(表名以 # 开头)会创建一个临时表,该表通常存储在内存中。对您来说似乎并非如此,从而导致昂贵的磁盘 i/o。对于内存表,如果结果大小不是太大,临时表应该会有所帮助
    【解决方案6】:

    一种解决方案是将其包装在子查询中

    SELECT *
    FROM
    (
        SELECT COUNT(column1),column1 FROM table GROUP BY column1
        UNION ALL
        SELECT COUNT(column2),column2 FROM table GROUP BY column2
        UNION ALL
        SELECT COUNT(column3),column3 FROM table GROUP BY column3
    ) s
    

    【讨论】:

    • 这不会多次“计算”表吗?
    • 无论如何都要计算三遍。您不能按三个不同的字段进行分组,并期望系统不必为每个不同的分组重新计算。从表面上看,这是不可能的。将它们放入单个查询中可能允许系统重用视图,但如果不是,我会调查索引,或者如果失败,则调查临时表。
    • 我在所有需要计数的列中都有索引。此查询未优化,因为表必须是子查询(SELECT column1 FROM table JOIN table2 ON ... WHERE ....)并且它再次计算子查询。我在考虑非规范化,这样我就没有连接了。。创建临时表也有点费时。。
    • 太棒了。如果你添加一些关于你的查询的描述会更方便。
    猜你喜欢
    • 2019-03-19
    • 1970-01-01
    • 1970-01-01
    • 2011-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多