动态MySQL查询/视图的交叉表

我目前有一个使用以下sql的硬编码视图:

select username

,(case user_role.role_id when 1 then true else false end) as ROLE_SUPER

,(case user_role.role_id when 2 then true else false end) as ROLE_ADMIN

,(case user_role.role_id when 3 then true else false end) as ROLE_VIEW

,(case user_role.role_id when 4 then true else false end) as ROLE_USER

,(case user_role.role_id when 5 then true else false end) as ROLE_EMAIL

from user

left outer join user_role on user.id=user_role.user_id

left outer join role on user_role.role_id = role.id;

我的问题是是否可以从角色表中的记录动态生成角色列。

回答:

可以 做您想做的事,但是我不确定 为什么

要这么做。获得动态列别名后,如何计划引用它们?也就是说,如果您从数据库中提取列别名,那么您将如何使用它们呢?我可能错过了您提出问题的原因。

无论如何,我假设您具有这样的结构:

CREATE TABLE `user` (

`id` int(11) NOT NULL auto_increment,

`username` varchar(255) default NULL,

PRIMARY KEY (`id`)

);

CREATE TABLE `role` (

`id` int(11) NOT NULL auto_increment,

`role` varchar(255) default NULL,

PRIMARY KEY (`id`)

);

CREATE TABLE `user_role` (

`user_id` int(11),

`role_id` int(11),

PRIMARY KEY (`user_id`, `role_id`)

);

INSERT INTO `user` (`username`) VALUES

('Bob'), ('Alice'), ('Carol'), ('Dave'), ('Eve');

INSERT INTO `role` (`role`) VALUES

('Super'), ('Admin'), ('View'), ('User'), ('Email');

INSERT INTO `user_role` VALUES

(1,1), (2,2), (3,3), (4,4), (5,5);

由此,您可以获得有关用户及其角色的信息:

SELECT username, role.id AS role_id, role.role AS role FROM user_role

JOIN user ON user.id = user_role.user_id

JOIN role ON role.id = user_role.role_id;

+----------+---------+-------+

| username | role_id | role |

+----------+---------+-------+

| Bob | 1 | Super |

| Alice | 2 | Admin |

| Carol | 3 | View |

| Dave | 4 | User |

| Eve | 5 | Email |

+----------+---------+-------+

您还可以为特定角色创建列别名:

SELECT username, (role.id = 1) AS Super FROM user_role

JOIN user ON user.id = user_role.user_id

JOIN role ON role.id = user_role.role_id;

+----------+-------+

| username | Super |

+----------+-------+

| Bob | 1 |

| Alice | 0 |

| Carol | 0 |

| Dave | 0 |

| Eve | 0 |

+----------+-------+

但是,如果我正确理解了您的问题,那么您想要做的就是根据角色名称生成列别名。您不能在MySQL语句中使用变量作为列别名,但是可以构造一个准备好的语句:

SET @sql = (SELECT CONCAT(

'SELECT username, ',

GROUP_CONCAT('(role.id = ', id, ') AS ', role SEPARATOR ', '),

' FROM user_role ',

'JOIN user ON user.id = user_role.user_id ',

'JOIN role ON role.id = user_role.role_id;')

FROM role);

SELECT @sql;

+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

| @sql |

+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

| SELECT username, (role.id = 1) AS Super, (role.id = 2) AS Admin, (role.id = 3) AS View, (role.id = 4) AS User, (role.id = 5) AS Email FROM user_role JOIN user ON user.id = user_role.user_id JOIN role ON role.id = user_role.role_id; |

+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

如您从输出中所见,它将生成一个包含SQL SELECT语句的字符串。现在,您需要从该字符串创建一个准备好的语句,并执行结果:

PREPARE stmt FROM @sql;

EXECUTE stmt;

+----------+-------+-------+------+------+-------+

| username | Super | Admin | View | User | Email |

+----------+-------+-------+------+------+-------+

| Bob | 1 | 0 | 0 | 0 | 0 |

| Alice | 0 | 1 | 0 | 0 | 0 |

| Carol | 0 | 0 | 1 | 0 | 0 |

| Dave | 0 | 0 | 0 | 1 | 0 |

| Eve | 0 | 0 | 0 | 0 | 1 |

+----------+-------+-------+------+------+-------+

为了使调用交叉表查询更容易,您可以将整个过程包装在存储过程中。在以下示例中,如上所述,我无法GROUP_CONCATSET

@sql语句内工作。相反,我不得不将其分成自己的变量。我不确定为什么这行不通,但是最终结果是相同的,并且代码的神秘性可能有所降低:

DELIMITER //

DROP PROCEDURE IF EXISTS test.crosstab//

CREATE PROCEDURE test.crosstab()

BEGIN

SET @cols = (SELECT GROUP_CONCAT(

'(role.id = ', id, ') AS ', role

SEPARATOR ', ') FROM role);

SET @sql = CONCAT(

'SELECT username, ',

@cols,

' FROM user_role ',

'JOIN user ON user.id = user_role.user_id ',

'JOIN role ON role.id = user_role.role_id;');

PREPARE stmt FROM @sql;

EXECUTE stmt;

END;

//

DELIMITER ;

CALL test.crosstab();

+----------+-------+-------+------+------+-------+

| username | Super | Admin | View | User | Email |

+----------+-------+-------+------+------+-------+

| Bob | 1 | 0 | 0 | 0 | 0 |

| Alice | 0 | 1 | 0 | 0 | 0 |

| Carol | 0 | 0 | 1 | 0 | 0 |

| Dave | 0 | 0 | 0 | 1 | 0 |

| Eve | 0 | 0 | 0 | 0 | 1 |

+----------+-------+-------+------+------+-------+

以上是 动态MySQL查询/视图的交叉表 的全部内容, 来源链接: utcz.com/qa/401214.html

回到顶部