基于视图或3表查询的MySQL数据透视

时间:2015-11-17 17:53:12

标签: mysql pivot-table

我希望在单个视图中汇总表中的查询但是卡住了!简化版本如下:

表1 users

usrID      usrName
1          Adam
2          Ben
3          Charlie

表2 groups

grpID      grpName
A          Soccer
B          Baseball
C          Golf

表3 users2groups

usrID      grpID      accessLevel
1          A          a
2          A          e
2          C          v
3          B          v

我想总结一下:

usrName    Soccer    Baseball     Golf
Adam       a         NULL         NULL
Ben        e         NULL         c
Charlie    NULL      v            NULL

我设法创建了一个查询,列出所有条目并将其保存为名为permissions的MySQL视图:

SELECT users.usrName, groups.grpName, users2groups.accessLevel FROM ((`users` JOIN `groups`) LEFT JOIN `users2groups` ON (((`users2groups`.`usrID` = `users`.`usrID`) AND (`users2groups`.`grpID` = `groups`.`grpID`)))))

从这里和其他地方看,我发现了一个数据透视表功能:

SET @sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
  'MAX(IF(grpName = ''',
  grpName,
  ''', value, NULL)) AS ',
  grpName
)
) INTO @sql
FROM permissions;
SET @sql = CONCAT('SELECT usrName, ', @sql, ' FROM permissions GROUP BY usrID');

但是当我尝试在MySQL Workbench中使用我的MySQL视图运行它时,我得到Error Code: 1146. Table 'MYDB.permissions' doesn't exist。我尝试用视图基于上面(括号中)的查询替换"permissions",但是虽然它似乎运行没有错误,但我没有显示结果集。

1 个答案:

答案 0 :(得分:0)

您的查询构建正确,但有些细节除外:

  1. 您忘记在视图中加入usrId字段(您在透视查询中使用它,因此需要将其放入)
  2. 您在透视查询中添加的value字段是什么?我认为你的意思是accessLevel
  3. 除了这两个小错误之外,我认为没有其他问题。

    执行此类操作时的最后一步是创建一个预准备语句来运行存储在@sql变量中的查询。

    下面我添加了更正后的脚本,它是指向SQL小提琴的链接(我在透视查询构造中使用case ... end而不是if(),但这只是一个偏好问题):

    SQL Fiddle

    MySQL 5.5架构设置

    CREATE TABLE users
        (`usrID` int, `usrName` varchar(7))
    ;
    
    INSERT INTO users
        (`usrID`, `usrName`)
    VALUES
        (1, 'Adam'),
        (2, 'Ben'),
        (3, 'Charlie')
    ;
    
    
    CREATE TABLE groups
        (`grpID` varchar(1), `grpName` varchar(8))
    ;
    
    INSERT INTO groups
        (`grpID`, `grpName`)
    VALUES
        ('A', 'Soccer'),
        ('B', 'Baseball'),
        ('C', 'Golf')
    ;
    
    
    CREATE TABLE users2groups
        (`usrID` int, `grpID` varchar(1), `accessLevel` varchar(1))
    ;
    
    INSERT INTO users2groups
        (`usrID`, `grpID`, `accessLevel`)
    VALUES
        (1, 'A', 'a'),
        (2, 'A', 'e'),
        (2, 'C', 'v'),
        (3, 'B', 'v')
    ;
    CREATE 
        ALGORITHM = UNDEFINED 
        SQL SECURITY DEFINER
    VIEW `permissions` AS
        (SELECT 
                `users`.`usrId` as `usrId` -- You forgot to include this column in the view (you use it in your pivot query)
              , `users`.`usrName` AS `usrName`
              , `groups`.`grpName` AS `grpName`
              , `users2groups`.`accessLevel` AS `accessLevel`
        FROM
            ((`users`
            JOIN `groups`)
            LEFT JOIN `users2groups` ON (((`users2groups`.`usrID` = `users`.`usrID`)
                AND (`users2groups`.`grpID` = `groups`.`grpID`))))
    )
    

    查询1

    SET @sql = NULL
    

    Results :(无结果)

    查询2

    SELECT GROUP_CONCAT(DISTINCT 
                        CONCAT(
                          'max(case grpName 
                                   when ''', grpName, ''' then accessLevel 
                                   else null
                               end) as `', grpName, '`'
                        )
                       ) INTO @sql
    FROM permissions
    

    Results :(无结果)

    查询3

    SET @sql = CONCAT('SELECT usrName, ', @sql, ' FROM permissions GROUP BY usrID')
    

    Results :(无结果)

    查询4

    -- Prepare the statement
    prepare stmt from @sql
    

    Results :(无结果)

    查询5

    -- Execute the statement
    execute stmt
    

    <强> Results

    | usrName | Soccer | Baseball |   Golf |
    |---------|--------|----------|--------|
    |    Adam |      a |   (null) | (null) |
    |     Ben |      e |   (null) |      v |
    | Charlie | (null) |        v | (null) |
    

    查询6

    -- When you're done, don't forget to deallocate the prepared statement
    deallocate prepare stmt
    

    Results :(无结果)