我目前有一个使用以下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_CONCAT
在SET @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 |
+----------+-------+-------+------+------+-------+
问题内容: 问题1: 我有一个具有以下结构和数据的表: 我想以以下格式显示这些记录: 我知道我需要使用交叉表/数据透视查询来获得此显示。为此,我基于对它的有限知识对其进行了尝试。以下是我的查询: 根据此查询,我得到以下显示: 任何人都可以帮助我对查询进行适当的更改以获取单行而不是如上所述的多行记录。 问题2: 还有一种方法可以获取特定字段的值作为列的名称。正如你可以在上面看到我有,,…作为标题。取
问题内容: 我有这个表视图 如何创建将在Oracle 10g中提供此透视图视图的查询? 有没有办法动态地做到这一点?我看到了很多方法(解码,PL / SQL循环,联合,11g数据透视) 但根据上述示例,我尚未找到适合我的方法 编辑 :我不知道在开发时间产品的数量或类型,所以这必须是动态的 问题答案: Oracle 11g是第一个支持PIVOT / UNPIVOT的,因此您必须使用: 您可以使用DE
问题内容: 我正在使用下表存储产品数据: 使用以下查询从两个表中选择记录 一切都正常工作:) 因为我动态地填充了“附加”表,所以如果查询也是动态的,那就很好了。这样,我不必每次输入新的字段名和字段值就更改查询。 问题答案: MySQL中动态执行此操作的唯一方法是使用Prepared语句。这是一篇关于它们的好文章: 动态数据透视表(将行转换为列) 您的代码如下所示: 观看演示 注意:GROUP_CO
找到那个预定红绿船的水手了吗?相交 我知道intersect在mysql中不起作用,所以我正在寻找替代方案
问题内容: 我在SQL Server中使用交叉表查询时遇到问题。 假设我有以下数据: 我想查询显示结果如下: 我如何查询以显示这样的输出? 笔记: 主题名称: C C ++ 英语 数据库 数学 将根据学生学习的学科而有所不同。 请访问http://sqlfiddle.com/#!6/2ba07/1来测试此查询。 问题答案: 有两种方法可以执行对值进行硬编码的静态方法和执行时确定列的动态方法。 即使
问题内容: 我正在使用MySQL。这是我的桌子 我需要一个选择查询来显示类似这样的表。 问题答案: 您可以使用此查询- 它产生您想要的结果。但是,如果您想动态地进行操作,请参阅这篇文章“自动执行数据透视表查询”-http: //www.artfulsoftware.com/infotree/queries.php#523,或者该链接- 动态数据透视表。