mysql - 如何在外部查询和子查询中对同一个表进行不同的分组

标签 mysql

表格如下所示:

id | number       | provider| datetime | keyword|country| 
1  | 1            | Mobitel |2012-11-05|    JAM |    RS |       
2  | 2            | Telekom |2013-04-25|   ASTRO|    RS |           
3  | 1            | Si.Mobil|2013-04-27|  DOMACE|    BA |             
4  | 4            | Telenor |2013-04-21|    BIP |    HR |      
5  | 7            | VIP     |2013-04-18|    WIN |    CZ |       
6  | 13           | VIP     |2014-05-21|  DOMACE|    RS |       
7  | 5            | VIP     |2014-06-04|    WIN |    HU |

我需要在一次查询中对按关键字和国家/地区分组的所有数字求和,并再次对按关键字、国家/地区和提供商分组的所有数字求和。

我是这样尝试的:

SELECT (SELECT SUM(number),country, keyword  
        FROM daily_subscriptions 
        WHERE datetime >= '2016-02-01  23:59:59'  
        GROUP BY country, keyword ) 
    num_of_all_subs, 
    SUM(number) as num_of_subs,
    country, 
    keyword, 
    provider  
FROM daily_subscriptions  
WHERE datetime >= '2016-02-01  23:59:59'  
GROUP BY country, keyword, provider

但是这个查询会抛出一个错误:

#1241 - Operand should contain 1 column(s)

这是我期望得到的:

id | num_of_all_subs|num_of_subs | provider| datetime | keyword|country| 
1  | 19             | 4          | Mobitel |2012-11-05|    JAM |    RS |       
2  | 12             | 5          |Telekom  |2013-04-25|   ASTRO|    RS |        
3  | 18             | 1          |Si.Mobil |2013-04-27|  DOMACE|    BA |          
4  | 42             | 21         |Telenor  |2013-04-21|    BIP |    HR |      
5  | 76             | 23         |VIP      |2013-04-18|    WIN |    CZ |       
6  | 13             | 3          |VIP      |2014-05-21|  DOMACE|    RS |       
7  | 53             | 11         |VIP      |2014-06-04|    WIN |    HU | 

字段 num_of_all_subs 表示 JAM(关键字)和 RS(国家/地区)的所有数字之和为 19,但每个 Mobitel(提供商)为 num_of_subs 4 来自所有 19 个,因为该国家/地区和关键字还有其他提供程序(即使它们未显示在表架构中)。

请帮我提取这些数据,因为我卡住了。

最佳答案

num_of_all_subs 的子查询(它是一个数字)必须只返回一列,下一个问题返回一行。此外,此子查询将在您分组之前进行评估,而您实际上想要首先分组并获取列 num_of_subscountrykeywordprovider,然后向第一个结果集添加另一列 num_of_all_subs

您可以完全按照刚刚描述的方式执行此操作:首先获取分组子查询(此处称为 details),然后使用依赖子查询为该子查询中的每一行获取 的值>num_of_all_subs 通过查看表格(再次)并对具有相同 providercountry 的所有行求和:

SELECT 
    (SELECT SUM(number)
     FROM daily_subscriptions ds
     WHERE datetime >= '2016-02-01  23:59:59'  
      and ds.country = details.country 
      and ds.keyword = details.keyword
    ) as num_of_all_subs,
    details.*
from
(select 
    SUM(number) as num_of_subs,
    country, 
    keyword, 
    provider  
 FROM daily_subscriptions  
 WHERE datetime >= '2016-02-01  23:59:59'  
 GROUP BY country, keyword, provider
) as details;

另一种方法是分别计算两组,一组包括 provider(details),另一组不包括(all_subs)。一个将包含 num_of_subs,一个将包含 num_of_all_subs。当这两个查询具有相同的 countrykeyword 时,您可以组合(join):

SELECT 
    all_subs.num_of_all_subs,
    details.*
from
(select 
    SUM(number) as num_of_subs,
    country, 
    keyword, 
    provider  
 FROM daily_subscriptions  
 WHERE datetime >= '2016-02-01  23:59:59'  
 GROUP BY country, keyword, provider
) as details
left join 
(SELECT 
    SUM(number) as num_of_all_subs,
    country, 
    keyword
 FROM daily_subscriptions
 WHERE datetime >= '2016-02-01  23:59:59'  
 GROUP BY country, keyword
) as all_subs
on all_subs.keyword = details.keyword and all_subs.country = details.country;

在您的情况下,您可以使用 join 而不是 left join,因为第一个子查询中的每一行都将在第二个子查询中有一行,尽管它是通常更安全的方法是保留它。

虽然理论上,MySQL 可以相同地执行这些查询(并且对于不太复杂的查询,它实际上会在可能和有用的情况下优化和处理依赖子查询,如连接),在当前的 MySQL 版本中,情况很可能不是这样第二个选项可能更快。无论如何,对于这两个版本,(country, keyword, provider) 上的复合索引都会产生奇迹。

关于mysql - 如何在外部查询和子查询中对同一个表进行不同的分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42341883/

相关文章:

php - 使用 php 向上或向下移动 mysql 数据库行

mysql - 更新表格单元格时自动插入

mysql - 如何在 codeigniter 中使用 where 和 join

php - 如何划分存储在 phpmyadmin 数据库中的字符串并以任意顺序从该字符串中搜索单词?

php - 如何为mysql创建DROP INDEX IF EXISTS?

MySQL - 连接和计算来自另一个表的行

mysql - zend 适配器类的 fetchall 函数不起作用

php - 如何获取从今天开始的记录?

php - TYPO3 6.2 -> PHP 5.3 -> MySQL 问题

mysql - 将另一个字段的条件转化为总和