使用GROUP BY的mysql pivot查询结果
我有一个要导出到CSV的数据表。理想情况下,我希望切换行和列,以便更好地分组数据 为了进一步解释,目前数据库如下所示使用GROUP BY的mysql pivot查询结果,mysql,csv,pivot,Mysql,Csv,Pivot,我有一个要导出到CSV的数据表。理想情况下,我希望切换行和列,以便更好地分组数据 为了进一步解释,目前数据库如下所示 data_id data_timestamp data_value -------------------------------------------- 1 2011-07-07 00:01:00 0.400 1 2011-07-07 00:02:00 0.500 1
data_id data_timestamp data_value
--------------------------------------------
1 2011-07-07 00:01:00 0.400
1 2011-07-07 00:02:00 0.500
1 2011-07-07 00:03:00 0.600
1 2011-07-07 00:04:00 0.700
2 2011-07-07 00:01:00 0.100
2 2011-07-07 00:02:00 0.200
2 2011-07-07 00:03:00 0.250
2 2011-07-07 00:04:00 2.300
我想做的是用data_timestamp值对data_值进行分组,这样时间戳就被分组了,每个data_id的每个data_值都显示在一列中,而不是一行中
data_timestamp input_1 input_2
--------------------------------------------
2011-07-07 00:01:00 0.400 0.100
2011-07-07 00:02:00 0.500 0.200
2011-07-07 00:03:00 0.600 0.250
2011-07-07 00:04:00 0.700 2.300
下面是我正在使用的查询
SELECT d.data_timestamp, d.input_1, d.input_2
FROM (
SELECT data_timestamp,
IF(data_id=1,data_value,NULL) AS 'input_1',
IF(data_id=2,data_value,NULL) AS 'input_2' FROM data
) AS d ORDER BY data_timestamp ASC
但这并不是我想要的,因为现在只要一个数据id没有值,就会有空值。GROUP BY似乎也对数据值进行分组,这不是我想要的
有什么建议吗
编辑:
我已经尝试在外部查询中使用WHERE d.input_1 NOT NULL,但无法获得结果
在那之前
data_timestamp input_1 input_2
--------------------------------------------
2011-07-07 00:01:00 0.400 NULL
2011-07-07 00:01:00 NULL 0.100
2011-07-07 00:02:00 0.500 NULL
2011-07-07 00:02:00 NULL 0.200
2011-07-07 00:03:00 0.600 NULL
2011-07-07 00:03:00 NULL 0.250
2011-07-07 00:04:00 0.700 NULL
2011-07-07 00:04:00 NULL 2.300
添加d.input_1不为NULL的位置将删除输入_2值
data_timestamp input_1 input_2
--------------------------------------------
2011-07-07 00:01:00 0.400 NULL
2011-07-07 00:02:00 0.500 NULL
2011-07-07 00:03:00 0.600 NULL
2011-07-07 00:04:00 0.700 NULL
而且,事实上,我有大约20个id要分组,因此不是最好的想法,也不是所有的想法。只需将表格本身加入即可
SELECT dt1.data_timestamp, dt1.input_1, dt2.input_2
FROM data_timestamp dt1
JOIN data_timestamp dt2
on dt1.data_timestamp = dt2.data_timestamp
and dt2.input_1 is null
WHERE dt1.input_2 is null;
请注意,此查询假定每个输入值都存在输入值2。如果不是这种情况,使用
左连接
或交叉连接
等透视
进行旋转既不容易(也不好)。我更喜欢使用案例
:
SELECT d.data_timestamp
, SUM( CASE WHEN data_id = 1 THEN data_value ELSE 0 END ) AS 'input_1'
, SUM( CASE WHEN data_id = 2 THEN data_value ELSE 0 END ) AS 'input_2'
...
, SUM( CASE WHEN data_id = 20 THEN data_value ELSE 0 END ) AS 'input_20'
FROM data
GROUP BY data_timestamp
ORDER BY data_timestamp ASC
但是如果
也在MySQL中工作:
SELECT d.data_timestamp
, SUM( IF(data_id = 1, data_value, 0) ) AS 'input_1'
, SUM( IF(data_id = 2, data_value, 0) ) AS 'input_2'
...
, SUM( IF(data_id = 20, data_value, 0) ) AS 'input_20'
FROM data
GROUP BY data_timestamp
ORDER BY data_timestamp ASC
或者,您可以使用20级连接:
SELECT d.data_timestamp
, d01.data_value AS 'input_1'
, d02.data_value AS 'input_2'
...
, d20.data_value AS 'input_20'
FROM
( SELECT DISTINCT d.data_timestamp
FROM data
) AS d
LEFT JOIN data AS d01
ON d01.data_timestamp = d.data_timestamp
AND d01.data_id = 1
LEFT JOIN data AS d02
ON d02.data_timestamp = d.data_timestamp
AND d02.data_id = 2
... --- 20 JOINs
LEFT JOIN data AS d20
ON d20.data_timestamp = d.data_timestamp
AND d20.data_id = 20
ORDER BY d.data_timestamp ASC
为什么不在外部查询中添加一个WHERE
子句来过滤NULL
值呢?@Michael,我确实有一个WHERE d.input_1 not NULL,它对第一个id很有效,但对第二个id却不有效。我对它进行了编辑以说明..那么为什么不添加和d.input_2不为空呢
?我尝试过,但那根本不会返回任何结果,因为当input_1和input_2都为空时不会出现这种情况。一个总是有一个值,当另一个为空时…因此,您可以使用IF
来选择非空的值。我不希望使用20级连接(这让我感到紧张),但您的大小写(和IF)实际上是我很久以前使用的(后来忘记了)。吸引我的是SUM的使用,它实际上并不是所有分组结果的总和。非常感谢@crawf:你可以通过20级连接进行测试。它可能更快:)经过几次测试,它比IF解决方案稍微快一点。我很惊讶,我不认为参加那么多次会更快。再次感谢@crawf:欢迎,使用大表进行测试,例如100K行和更多行(并保留较快的一行)。如果有机会,你可以用它来处理这么多的数据。如果我能接受两个答案,我会的!这就是我投票支持它的原因。问题是我有20个数据ID要加入。对于yor解决方案,我需要有20个不同的连接,这是我不喜欢的(并且不确定这将如何降低性能)。我不是故意不接受,这对于一个包含2个数据ID的表来说是完美的!