MySQL CrossTab结果包含非不同的列

时间:2016-07-02 13:29:40

标签: mysql

两部分问题:

  1. 在生成MySql的交叉表结果时,Distinct调用似乎不起作用......或者我错过了其他内容?我在几列中得到了相同的ClassName。即“MDC(介绍)”。

  2. SQLFiddle中的现有示例会产生结果(虽然不正确),但是当移动到托管的MySql时,它会失败并显示错误: #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'el FROM EnrollmentsTblx GROUP BY AutoNum' at line 1

  3. SQL:

    SET @sql = NULL;
    SELECT
      GROUP_CONCAT(
        DISTINCT
        CONCAT(
          ' GROUP_CONCAT((CASE ClassName when ', CHAR(39), 
          ClassName, CHAR(39),
          ' then ', CHAR(39), DateCompleted, CHAR(39), ' else NULL END)) AS `',
          ClassName, '`'
        )
      ) INTO @sql
    FROM EnrollmentsTbl;
    
    
    SET @sql = CONCAT('SELECT AutoNum, UserName, ', @sql, ' 
                  FROM EnrollmentsTbl 
                  GROUP BY AutoNum, UserName');
    
    SELECT @sql;
    PREPARE stmt FROM @sql;
    EXECUTE stmt;
    DEALLOCATE PREPARE stmt;
    

    Schems:

    SET NAMES 'UTF8';
    
    CREATE TABLE `EnrollmentsTbl` (
    `AutoNum` INTEGER PRIMARY KEY,
    `UserName` VARCHAR(50),
    `SubmitTime` DATETIME,
    `ClassName` VARCHAR(50),
    `ClassDate` DATETIME,
    `ClassTime` VARCHAR(50),
    `Enrolled` BOOLEAN,
    `WaitListed` BOOLEAN,
    `Instructor` VARCHAR(50),
    `DateCompleted` DATETIME,
    `Completed` BOOLEAN,
    `EnrollmentsMisc` VARCHAR(50),
    `Walkin` BOOLEAN
    ) CHARACTER SET 'UTF8';
    
    INSERT INTO      `EnrollmentsTbl`(`AutoNum`,`UserName`,`SubmitTime`,`ClassName`,`ClassDate`,`ClassTime`,`Enrolled`,`WaitListed`,`Instructor`,`DateCompleted`,`Completed`,`EnrollmentsMisc`,`Walkin`)
    VALUES(1,'John',NULL,'MDC (Intro)','2004-06-27 00:00:00',NULL,TRUE,FALSE,'Phil','2004-06-27 00:00:00',TRUE,NULL,FALSE),
      (2,'Bob',NULL,'MDC (Intro)','2004-06-27 00:00:00',NULL,TRUE,FALSE,'Phil','2004-06-27 00:00:00',TRUE,NULL,FALSE),
      (3,'Robert',NULL,'MDC (Intro)','2004-06-27 00:00:00',NULL,TRUE,FALSE,'Phil','2004-06-27 00:00:00',TRUE,NULL,FALSE),
      (4,'John','2010-08-04 06:11:10','HIPAA (Employee)','2010-08-04 00:00:00','6:12 AM',TRUE,FALSE,'On-line','2010-08-04 06:11:10',TRUE,NULL,FALSE),
      (5,'Debbie',NULL,'MDC (Intro)','2003-04-19 14:53:55',NULL,TRUE,FALSE,'devore','2003-04-19 14:53:55',TRUE,NULL,FALSE),
      (6,'Jeff',NULL,'MDC (Intro)','2003-03-29 14:26:23',NULL,TRUE,FALSE,'','2003-03-29 14:26:23',TRUE,NULL,FALSE),
      (7,'Tom',NULL,'Firehouse (Incident)','2004-07-13 00:00:00',NULL,TRUE,FALSE,'Shannon','2004-07-13 00:00:00',TRUE,NULL,FALSE),
      (8,'Janet','2016-06-30 14:02:05','MDC (On-Line)','2016-06-30 00:00:00','2:02 PM',TRUE,FALSE,'On-line','2016-06-30    14:02:05',TRUE,NULL,FALSE);
    

    小提琴屏幕截图:

    enter image description here

    我在Access数据库中使用SQL作为SQL:

    TRANSFORM DateCompleted
    SELECT UserName
    FROM EnrollmentsTbl
    GROUP BY UserName
    ORDER BY UserName
    PIVOT ClassName
    

    期望的结果如下所示:

    UserName    MDC (Intro)     HIPAA (Employee)    Firehouse (Incident)
    --------    -----------     ----------------    --------------------
    John        6-27-2004       10-4-2006           8-6-2005
    Bob         6-27-2004                           
    Robert      6-27-2004                           8-6-2005
    Debbie      4-19-2003
    Jeff                                            11-25-2006
    Tom                         7-13-2004
    Janet                       11-25-2006
    

3 个答案:

答案 0 :(得分:1)

您的字符串在每个引号之前都有一个转义\

为了证明这一点,我将它转储到文本编辑器(MySQL Workbench)中,在创建表格后很明显。我为查找和替换做了一个ctrl-H,(\'到了'),并且能够执行准备好的stmt并获得结果集。

在系统(或shell或各种编程语言)之间移动数据时,这是一个常见问题。我还注意到数据末尾有一些\n

此外,DISTINCT适用于所有列(不是每个列)。

在两列输出上如此明显会导致以下容易:

class    student
-------  ----------
ABC      Drew
ABC      Barlay

查看mysql replace()函数,或者:

SELECT 
  GROUP_CONCAT(
    DISTINCT
    CONCAT(
      ' GROUP_CONCAT((CASE ClassName when \'',  
      ClassName,  
      '\' then \'',DateCompleted,'\' else NULL END)) AS `',
      ClassName, '`'
    )
  ) INTO @sql
FROM EnrollmentsTbl;
SET @sql = CONCAT("SELECT AutoNum, UserName, ", @sql, " FROM EnrollmentsTbl GROUP BY AutoNum, UserName");

select @sql;

呈现:

SELECT AutoNum, UserName,  GROUP_CONCAT((CASE ClassName when 'MDC (Intro)' then '2004-06-27 00:00:00' else NULL END)) AS `MDC (Intro)`, GROUP_CONCAT((CASE ClassName when 'HIPAA (Employee)' then '2010-08-04 06:11:10' else NULL END)) AS `HIPAA (Employee)`, GROUP_CONCAT((CASE ClassName when 'MDC (Intro)' then '2003-04-19 14:53:55' else NULL END)) AS `MDC (Intro)`, GROUP_CONCAT((CASE ClassName when 'MDC (Intro)' then '2003-03-29 14:26:23' else NULL END)) AS `MDC (Intro)`, GROUP_CONCAT((CASE ClassName when 'Firehouse (Incident)' then '2004-07-13 00:00:00' else NULL END)) AS `Firehouse (Incident)`, GROUP_CONCAT((CASE ClassName when 'MDC (On-Line)' then '2016-06-30 14:02:05' else NULL END)) AS `MDC (On-Line)` FROM EnrollmentsTbl GROUP BY AutoNum, UserName
-- Drew used above

像逃脱序列方面的魅力一样工作。

有关为什么在concat()上使用双引号的一点点了解,好吧,使用单引号导致@sql的prev值使用\转义其单引号因此可能会导致系统出现1064错误。因此,如果将字符串放在一起的第二部分,你可能已经无家可归了。

始终暂停并查看步骤之间的字符串,以查看状态是什么状态,以及未执行的操作。

现在谈谈你的DISTINCT数据问题(那是关于堆栈的新问题,而不是这里)

答案 1 :(得分:0)

这似乎是我得到的最接近期望的结果,唯一的问题是它返回一个计数而不是完成的日期:

SELECT  `UserName`,
COUNT(
    CASE 
        WHEN `ClassName`='MDC (Intro)' 
        THEN `DateCompleted` 
        ELSE NULL 
    END
) AS 'MDC',
COUNT(
    CASE 
        WHEN `ClassName`='HIPAA(Employee)' 
        THEN `DateCompleted` 
        ELSE NULL 
    END
) AS 'HIPAA',
COUNT(
    CASE 
        WHEN `ClassName`='Firehouse (Incident)' 
        THEN `DateCompleted`
        ELSE NULL 
    END
) AS 'Firehouse'
FROM    EnrollmentsTbl
GROUP BY `UserName`;

SQLFiddle Example

示例来自:MySQL pivot table

答案 2 :(得分:0)

不像我想要的那样动态,但根据需要进行了格式化。

解决:

SELECT  `UserName`,
    MAX(IF(`ClassName`='MDC (Intro)', `DateCompleted`, NULL)) AS 'MDC', 
    MAX(IF(`ClassName`='HIPAA (Employee)', `DateCompleted`, NULL)) AS 'HIPAA',
    MAX(IF(`ClassName`='MDC (On-Line)', `DateCompleted`, NULL)) AS 'MDC-OL',
    MAX(IF(`ClassName`='Firehouse (Incident)', `DateCompleted`, NULL)) AS 'Fierhouse'
FROM    EnrollmentsTbl
GROUP BY `UserName`;

工作示例: SQLFiddle