SQL(MYSQL)选择列名称的列名称> 0

时间:2014-08-08 15:10:30

标签: mysql sql

我在构建查询时遇到问题,需要帮助。请考虑以下MYSQL表。

用户表

username
tuser
tman
tester

usergrouplink table

username|groupname
tuser   |grp1
tuser   |grp2

组表

groupname|reporter|provisioner|manager
grp1     |0       |0          |1
grp2     |0       |1          |1
grp3     |1       |0          |0

组表根据位标志(0或1)将组名称(grp1)链接到角色(报告者,供应者,管理者)

我需要一个可以返回给定用户名的角色名列表的查询。例如,给定用户' tuser'在grp1和grp2中,返回供应商和经理的角色列表

Role
provisioner
manager

我尝试了以下内容,它似乎有效,但我必须找到一种方法来简化它:

select distinct Role, 'Roles' from
(
    select 'Reporter' as Role from
    (
        select * from Groups g where g.name in 
        (
            select groupname from UserGroupLink l where l.username='tuser'
        )
    ) x
    where x.reporter>0

    union

    select 'Provisioner' as Role from
    (
        select * from Groups g where g.name in 
        (
            select groupname from UserGroupLink l where l.username='tuser'
        )
    ) x
    where x.provisioner>0

    union

    select 'Manager' as Role from
    (
        select * from Groups g where g.name in 
        (
            select groupname from UserGroupLink l where l.username='tuser'
        )
    ) x
    where x.manager>0
) z

以上查询有效,但会与用户名' tuser'进行比较。三次,每个角色一次。如果可能的话,我需要修改查询,只在一个地方使用用户名字符串文字(对于Java JAAS安全性,如果有人好奇的话)。有谁知道这是否可行?

1 个答案:

答案 0 :(得分:1)

如果您不介意将角色放入一行,您可以执行以下操作:

select concat_ws(',',
                 (case when reporter > 0 then 'Reporter'
                       when Provisioner > 0 then 'Provisioner'
                       when Manager > 0 then 'Manager'
                  end)
                ) as roles
from user u join
     usergrouplink ugl
     on u.tuser = ugl.tuser join
     groups g
     on ugl.groupname = g.groupname
where u.name = 'tuser';

如果您有控制权,则应考虑通过创建groups表来规范化GroupRoles表,每个组一个角色,每个角色一行。

编辑:

如果您需要多行,您仍然可以这样做。把它放在一行就更容易了:

select (case when reporter > 0 and n.n = 1 then 'Reporter'
             when Provisioner > 0 and n.n = 2 then 'Provisioner'
             when Manager > 0 and n.n = 3 then 'Manager'
        end) as role
from user u join
     usergrouplink ugl
     on u.tuser = ugl.tuser join
     groups g
     on ugl.groupname = g.groupname cross join
     (select 1 as n union all select 2 union all select 3
     ) n
where u.name = 'tuser'
having role is not NULL;

请注意,这会使用MySQL中的having子句扩展。您可以在没有group by的情况下使用它,并为条件使用列别名。否则,逻辑将需要子查询或复杂的where语句。