MySql查询通过DATA_FORMAT分组动态地将行转换为列

时间:2015-07-09 14:16:18

标签: mysql sql

我的MySQL 5.5数据库中有两个表:

CREATE TABLE `t_user` (
  `USER_ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `USER_NAME` varchar(255) NOT NULL,
  PRIMARY KEY (`USER_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

CREATE TABLE `t_user_activity_log` (
  `USER_ID` int(10) unsigned NOT NULL,
  `ACTIVITY_DATE` datetime NOT NULL,
  `ACTIVITY_COUNT` int(10) unsigned NOT NULL,
  PRIMARY KEY (`USER_ID`,`ACTIVITY_DATE`),
  CONSTRAINT `FK_t_user` FOREIGN KEY (`USER_ID`) REFERENCES `t_user` (`USER_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

我需要按照时间段分组结果:

----------------------------------------------
| Period     | User1 | User2 | ***** | UserN |
----------------------------------------------
| 22.02.2012 |   12  |   12  |   x   |   x   |
----------------------------------------------
| 23.02.2012 |   7   |   3   |   x   |   x   |
----------------------------------------------
| 24.02.2012 |   0   |   0   |   0   |   0   |
----------------------------------------------

期间可变(小时,星期,月,年)。应该可以通过FROM和TO日期限制查询,如果没有找到日期记录 - 它应该仍然在结果中可见。应从列表in()中选择用户。

有可能吗?

2 个答案:

答案 0 :(得分:0)

您可以执行类似的操作,显然您可以使用实际用户列表中的服务器语言生成此查询。

SELECT 
t.ACTIVITY_DATE,
SUM(IF(t.USER_ID = 1, t.activity_count, 0)) as 'user1',
SUM(IF(t.USER_ID = 2, t.activity_count, 0)) as 'user2'

FROM (
SELECT t_user.USER_ID, 
    t_user.USER_NAME, 
    t_user_activity_log.ACTIVITY_DATE, 
    SUM(t_user_activity_log.ACTIVITY_COUNT) as activity_count
FROM t_user_activity_log 
INNER JOIN t_user ON t_user_activity_log.USER_ID = t_user.USER_ID

GROUP BY t_user.USER_ID, t_user_activity_log.ACTIVITY_DATE
) as t

GROUP BY t.USER_ID, t.ACTIVITY_DATE

答案 1 :(得分:0)

如果要将其保留在数据库中,可以在像

这样的过程中创建动态查询
    DELIMITER $$
DROP PROCEDURE IF EXISTS `dynamic_query`$$
CREATE PROCEDURE `dynamic_query`()
BEGIN
    DECLARE done INT DEFAULT FALSE;
    DECLARE user_id INT;
    DECLARE user_name VARCHAR(255);

    #Cursor to fetch all the users
    DECLARE cursor_user CURSOR FOR SELECT t_user.USER_ID, t_user.USER_NAME FROM t_user;


    DECLARE CONTINUE HANDLER 
    FOR NOT FOUND SET done = 1;

    # start of the dynamic query
    SET @query = CONCAT('SELECT t.ACTIVITY_DATE\n');

    OPEN cursor_user;
    # looping over the cursor
    user_loop: LOOP
        FETCH cursor_user INTO user_id, user_name;
        # Leaving the loop inf no more records found
        IF done = 1 THEN
            LEAVE user_loop;
        END IF;
        #Concatenate the users in the dynamic query
        SET @query = CONCAT(@query,',SUM(IF(t.USER_ID = ',user_id,', t.activity_count, 0)) as \'',user_name,'\'');
    END LOOP;

    CLOSE cursor_user;

    #the rest of the dynamic query
    SET @query = CONCAT(@query,' FROM (SELECT t_user.USER_ID, t_user.USER_NAME, t_user_activity_log.ACTIVITY_DATE, SUM(t_user_activity_log.ACTIVITY_COUNT) as activity_count FROM t_user_activity_log INNER JOIN t_user ON t_user_activity_log.USER_ID = t_user.USER_ID GROUP BY t_user.USER_ID, t_user_activity_log.ACTIVITY_DATE) as t GROUP BY t.USER_ID, t.ACTIVITY_DATE');

    # Preparing and executing the dynamic query
    PREPARE stmt FROM @query;
    EXECUTE stmt;

    # Cleaning up
    DEALLOCATE PREPARE stmt;

END$$
DELIMITER ;