我对mySQL数据库有一个非常复杂的SQL问题。 我将首先介绍这个问题所需的所有表格:
用户表:
Id date_created
------------------------------
1 2015-09-19T14:18:07.000Z
2 2015-09-20T01:16:34.000Z
3 2015-09-21T15:10:21.000Z
…
设置表:
Id User_id setting_key setting_value
----------------------------------------------
1 1 city 1
2 3 city 2
3 2 city 1
…
城市名称表:
Id name
------------------
1 New York
2 Los Angeles
3 Boston
…
使用select-query我想实现这个目标:
date New York Los Angeles Boston …
------------------------------------------------------
2015-09-19 1 0 0
2015-09-20 2 0 0
2015-09-21 2 1 0
…
对于某个范围内的每个日期,有多少用户设置纽约,洛杉矶,洛杉矶.... 我唯一能做到的就是这个查询:
select date(u.date_created), n.name, count(u.id)
from user u inner join setting s
on u.id = s.user_id
and setting_key = 'city'
inner join name n
on s.setting_value = n.id
where u.date_created > '2015-09-19T14:18:07.000Z'
group by 1, 2
然后我得到了这个结果:
date name count
-------------------------------
2015-09-19 New York 1
2015-09-19 Los Angeles 0
2015-09-19 Boston 0
2015-09-20 New York 1
2015-09-20 Los Angeles 0
2015-09-20 Boston 0
2015-09-21 New York 0
2015-09-21 Los Angeles 1
2015-09-21 Boston 0
…
每个城市都有行,而不是每个城市的列,这不是累积的。有人知道(复杂的)答案吗?如果问题不明确,请问,实际上这些是50.000行的表,我无法改变结构,我需要这个查询用于分析目的
答案 0 :(得分:1)
如果您知道城市的名称,只需使用条件聚合:
select date(u.date_created),
sum(name = 'New York') as NewYork,
sum(name = 'Los Angeles' as LosAngeles,
sum(name = 'Boston') as Boston
from user u inner join
setting s
on u.id = s.user_id and
setting_key = 'institution' inner join
education_niveau en
on s.setting_value = en.id
where u.date_created > '2015-09-19T14:18:07.000Z'
group by 1;
如果你不知道城市的名称或者有一个未知的数字,那么你将需要动态SQL - 即构造SQL,准备一个语句,然后执行它。
编辑:
起初并不是很明显这个问题是关于累积计数的。为此,使用变量:
select dte,
(@ny := @ny + NewYork) as NewYork,
(@la := @la + LosAngeles) as LosAngeles,
(@b := @b + Boston) as NewYork
from (select date(u.date_created) as dte,
sum(name = 'New York') as NewYork,
sum(name = 'Los Angeles' as LosAngeles,
sum(name = 'Boston') as Boston
from user u inner join
setting s
on u.id = s.user_id and
setting_key = 'institution' inner join
education_niveau en
on s.setting_value = en.id
where u.date_created > '2015-09-19T14:18:07.000Z'
group by 1
order by 1
) us cross join
(select @ny := 0, @la := 0, @b := 0) params
order by 1;
答案 1 :(得分:0)
你想要一个pivot,mysql本身不支持它。但是,这可能适合您:
select date, group_concat(concat(name, '=', uid_count)) cities
from (
select date(u.date_created) date, en.name, count(u.id) uid_count
from user u
join setting s on u.id = s.user_id
join education_niveau en on s.setting_value = en.id
where u.date_created > '2015-09-19T14:18:07.000Z'
and setting_key = 'institution'
group by 1, 2) x
group by 1
将产生如下结果:
date Cities
------------------------------------------------------
2015-09-19 New York=1
2015-09-20 New York=2
2015-09-21 New York=2,Los Angeles=1
这种方法的主要优点是返回的城市范围完全基于数据。