虽然我参加了sql课程的介绍,但我现在无法想出这个。
我有两张桌子:
表1:
user_id date value
ids dates values
表2:
user_id user_names
ids names
我想要一个显示以下结果的MYSQL查询:
/ name1 name2 name3 etc
date1 val1-1 val1-2 val1-3
date2 val2-1 val2-2 val2-3
我记得有办法做到这一点,对吧?任何帮助将不胜感激。
答案 0 :(得分:1)
以这种方式旋转数据称为 pivot 。不幸的是,MySQL没有pivot函数,所以你必须使用聚合函数和CASE
表达式来复制它。
示例数据
CREATE TABLE Table1
(`user_id` int, `date` datetime, `value` int)
;
INSERT INTO Table1
(`user_id`, `date`, `value`)
VALUES
(1, '2013-01-01 00:00:00', 100),
(2, '2013-01-01 00:00:00', 200),
(1, '2013-01-02 00:00:00', 500)
;
CREATE TABLE Table2
(`user_id` int, `user_names` varchar(4))
;
INSERT INTO Table2
(`user_id`, `user_names`)
VALUES
(1, 'John'),
(2, 'Tim')
;
如果您知道要转换为列的所有值(例如names
),那么您可以对它们进行硬编码,SQL将与此类似:
select
date,
max(case when rownum = 1 then value end) as John,
max(case when rownum = 2 then value end) as Tim
from
(
select date, value, user_names,
@row:=case when @prev=date then @row else 0 end + 1 as rownum,
@prev:=date
from
(
select t1.date, t1.value, t2.user_names
from table1 t1
inner join table2 t2
on t1.user_id = t2.user_id
order by date, user_names
) d, (SELECT @row:=0, @prev:=null) r
order by date, user_names
) src
group by date
见SQL Fiddle with Demo。如您所见,我必须实现用户变量,以便为日期中的每个名称分配行号。这会告诉您将有多少个不同的名称值转换为列。
但是,对于您的情况,每个日期的名称数量都是未知的,因此您需要在prepared statement内使用动态SQL。
在这种情况下,代码将类似于:
SET @sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'max(case when rownum = ',
rownum,
' then value end) AS `',
user_names, '`'
)
) INTO @sql
from
(
select date, value, user_names,
@row:=case when @prev=date then @row else 0 end + 1 as rownum,
@prev:=date
from
(
select t1.date, t1.value, t2.user_names
from table1 t1
inner join table2 t2
on t1.user_id = t2.user_id
order by date, user_names
) d, (SELECT @row:=0, @prev:=null) r
order by date, user_names
) src;
SET @sql = CONCAT('SELECT date, ', @sql, '
from
(
select date, value, user_names,
@row:=case when @prev=date then @row else 0 end + 1 as rownum,
@prev:=date
from
(
select t1.date, t1.value, t2.user_names
from table1 t1
inner join table2 t2
on t1.user_id = t2.user_id
order by date, user_names
) d, (SELECT @row:=0, @prev:=null) r
order by date, user_names
) src
group by date');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
见SQL Fiddle with Demo。两个版本都会给出结果:
| DATE | JOHN | TIM |
--------------------------------------------------
| January, 01 2013 00:00:00+0000 | 100 | 200 |
| January, 02 2013 00:00:00+0000 | 500 | (null) |
答案 1 :(得分:0)
使用内部联接加入两个表并保存为视图,然后使用此作为原始数据,PIVOT结果集,您将获得您所追求的结果。连接,视图创建和PIVOT应该都有大量的代码示例,并且应该很容易在课程结束后进行。
答案 2 :(得分:0)