表格如下:
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 - 操作数应包含1列
这是我期望得到的:
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,因为有该国家/地区和关键字的其他提供商(即使它们未显示在表架构中)。
请帮我提取这些数据,因为我被卡住了。
答案 0 :(得分:1)
num_of_all_subs
的子查询(单个数字)必须只返回一列,下一个问题是一行。此外,在您进行分组之前,将对此子查询进行评估,而您实际上希望首先分组并获取列num_of_subs
,country
,keyword
和provider
,之后,将另一列num_of_all_subs
添加到第一个结果集。
您可以完全按照上述描述执行此操作:首先获取分组子查询(此处称为details
),然后使用从属子查询为该子查询中的每一行获取num_of_all_subs
的值通过查看表格(再次)并总结具有相同provider
和country
的所有行:
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
。当这两个查询具有相同的join
和country
时,您可以合并(keyword
):
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)
上的复合索引都会产生奇迹。