查询中的SQL结果

时间:2013-05-10 09:59:15

标签: mysql sql sql-server database postgresql

不要责怪数据库设计。我不是它的数据库架构师。我是在当前情况下必须使用它的人

我希望这是可以理解的。 我有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。任何建议都将受到赞赏。

3 个答案:

答案 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