不要责怪数据库设计。我不是它的数据库架构师。我是在当前情况下必须使用它的人
我希望这是可以理解的。 我有3个表包含以下数据,没有外键关系b / w:
groups
groupId groupName
1 Admin
2 Editor
3 Subscriber
preveleges
groupId roles
1 1,2
2 2,3
3 1
roles
roleId roleTitle
1 add
2 edit
查询:
SELECT roles
from groups
LEFT JOIN preveleges ON (groups.groupId=preveleges.groupId)
返回特定结果,即角色。
问题:我想在上面的查询中显示 roleTitle 而不是角色。 我很困惑如何将表角色与此查询相关联并返回所需的结果
我知道编码是可行的,但我想要SQL。任何建议都将受到赞赏。
答案 0 :(得分:3)
SELECT g.groupName,
GROUP_CONCAT(r.roleTitle
ORDER BY FIND_IN_SET(r.roleId, p.roles))
AS RoleTitles
FROM groups AS g
LEFT JOIN preveleges AS p
ON g.groupId = p.groupId
LEFT JOIN roles AS r
ON FIND_IN_SET(r.roleId, p.roles)
GROUP BY g.groupName ;
经过测试: SQL-FIDDLE
答案 1 :(得分:2)
我会改变自己的数据结构。由于它没有标准化,因此单个列中有多个元素。
但是有可能使用SQL,如果由于某些(有效)原因你无法更改数据库。
一个简单的“静态”解决方案:
SELECT REPLACE(REPLACE(roles, '1', 'add'), '2', 'edit') from groups
LEFT JOIN preveleges ON(groups.groupId=preveleges.groupId)
更复杂但仍然难看的解决方案:
CREATE FUNCTION ReplaceRoleIDWithName (@StringIds VARCHAR(50))
RETURNS VARCHAR(50)
AS
BEGIN
DECLARE @RoleNames VARCHAR(50)
SET @RoleNames = @StringIds
SELECT @RoleNames = REPLACE(@RoleNames, CAST(RoleId AS VARCHAR(50)), roleTitle)
FROM roles
RETURN @RoleNames
END
然后在查询中使用该函数
SELECT ReplaceRoleIDWithName(roles) from groups
LEFT JOIN preveleges ON(groups.groupId=preveleges.groupId)
没有功能可以,但这更具可读性。没有编辑器制作,所以它还没有进行测试。
答案 2 :(得分:2)
你还用PostgreSQL标记了这个问题,而Postgres实际上很容易解决这个破碎的设计:
SELECT grp.groupname, r.roletitle
FROM groups grp
join (
select groupid, cast(regexp_split_to_table(roles, ',') as integer) as role_id
from privileges
) as privs on privs.groupid = grp.groupid
join roles r on r.roleid = privs.role_id;
SQLFiddle:http://sqlfiddle.com/#!12/5e87b/1
(请注意,我将拼写错误的名称preveleges
更改为正确的拼写privileges
)
但你应该,真的重新设计你的数据模型!
修复设计还可以定义外键约束并验证输入。在您当前的模型中,如果有人将值'one,two,three'
插入到角色表中,应用程序可能会中断(就像我的查询一样)。
修改强>
为了完成图片,使用Postgres的数组处理可以使用与MySQL的find_in_set()
select grp.groupname, r.roletitle
from groups grp
join privileges privs on grp.groupid = privs.groupid
join roles r on r.roleid::text = any (string_to_array(privs.roles, ','))
在这两种情况下,如果所有角色标题都应显示为以逗号分隔的列表,则可以使用string_agg()函数(这相当于MySQL的group_concat()
select grp.groupname, string_agg(r.roletitle, ',')
from groups grp
join privileges privs on grp.groupid = privs.groupid
join roles r on r.roleid::text = any (string_to_array(privs.roles, ','))
group by grp.groupname