sql将同一个表和同一列的值从一行中获取

时间:2018-04-23 19:40:08

标签: sql sql-server join

有两张桌子; X_User_Role 角色就像这样

X_User_Role表:

df1 <- data.frame(variable_name = c(rep('var1', 3),rep('var2',4), rep('var3', 3), rep('var4', 4)),
             var_value = c(1,4,2,4,3,6,2,1,6,3,1,3,2,4),
             value_type = c('A','B','C','A','B','C','D','B','C','D','B','D','E','F'))

df2 <- data.frame( variable_name = c(rep('var6',4), rep('var4', 4)),
             var_value = c(4,3,6,2,1,3,2,4),
             value_type = c('A','B','C','D','B','D','E','F'))

ggplot() + 
    geom_col(data = df1,
    aes(x = variable_name, y =var_value,fill = value_type), 
    width = 0.8)

ggplot() + 
    geom_col(data = df2,
    aes(x = variable_name, y =var_value,fill = value_type), 
    width = 0.8)

角色表:

************************
UserRoleID UserID RoleID
************************
1           1      1
************************
2           1      2
************************
3           2      1

现在我正在编写带连接的select语句,这样在我的最终输出中它应该是(仅考虑1个用户ID):

********************************
RoleID  Name         SecondaryFl
********************************
1       PrimaryRole    0
********************************
2       SecondaryRole  1      
********************************

我尝试过像这样加入:

UserID     PrimaryRoleName      SecondaryRoleName
***********************************************************
  1         PrimaryRole          SecondaryRole

但我总是得到这样的输出:

select xur.UserID, r1.Name as PrimaryRoleName, r2.Name as SecondaryRoleName
from X_User_Role xur 
JOIN Role r1
ON r1.RoleID = xur.RoleID
JOIN Role r2
ON r2.RoleID = r1.RoleID AND SecondaryFl = 1

我尝试了上述连接的不同变体,但我从未得到所需的输出。我无法弄清楚我做错了什么。我是SQL的新手。有人可以帮忙吗?

注意:我必须使用JOINS,因为这是一个更大的选择的一部分,它完全由JOINS组成。

6 个答案:

答案 0 :(得分:4)

应使用条件聚合

select xur.userId,
      max(case when SecondaryFl = 0 then r.name end) as PrimaryRoleName,
      max(case when SecondaryFl = 1 then r.name end) as SecondaryRoleName
from X_User_Role xur 
join Role r on r.RoleID = xur.RoleID
group by xur.userId;

编辑(YogeshSharma)

在执行条件聚合时始终包含where子句,因为如果SecondaryFl列的值超出上述值,那么它将包含 null 总是行。

select xur.userId,
       max(case when SecondaryFl = 0 then r.name end) as PrimaryRoleName,
       max(case when SecondaryFl = 1 then r.name end) as SecondaryRoleName
from X_User_Role xur 
join Role r on r.RoleID = xur.RoleID
where SecondaryFl in (1, 0) -- Always include especially for conditions aggregation 
group by xur.userId;

答案 1 :(得分:1)

我认为这个问题缺少一些事实。比如,哪个角色有资格成为次要角色?但是对于这个答案,我将假设SecondaryFl字段表明了这一点。 0表示主要,1表示次要。

我相信您遇到的问题是由于您的查询:

JOIN Role r2
ON r2.RoleID = r1.RoleID AND SecondaryFl = 1

由于您是第二次在同一主键上加入Role表。相反,你想再次加入它,但它有自己的条件。

像这样:

select
  user_role.UserID,
  role_primary.Name as PrimaryRoleName,
  role_secondary.Name as SecondaryRoleName
from X_User_Role as user_role 
join Role as role_primary
  on role_primary.RoleID = user_role.RoleID and SecondaryFl = 0
join Role as role_secondary
  on role_secondary.RoleID = user_role.RoleID and SecondaryFl = 1

很抱歉,我改变了你的名字,我发现它更具可读性。这应该说明我认为这一点更清楚了。

编辑:我认为角色总会在这里出现。如果角色是可选的,您可以改为使用left join,并使用类似coalesce(role_primary.Name, 'None')的方法处理返回的空值,或者只是将返回的空值视为接收结果的位置。

像这样:

select
  user_role.UserID,
  coalesce(role_primary.Name, 'None') as PrimaryRoleName,
  coalesce(role_secondary.Name, 'None') as SecondaryRoleName
from X_User_Role as user_role 
left join Role as role_primary
  on role_primary.RoleID = user_role.RoleID and SecondaryFl = 0
left join Role as role_secondary
  on role_secondary.RoleID = user_role.RoleID and SecondaryFl = 1

答案 2 :(得分:1)

您可以使用如下所示的数据透视查询 see live demo

在你的笔记上:

  

我必须使用JOINS,因为这是一个更大的选择的一部分,它完全由JOINS组成。

您始终可以在查询中将其封装为JOIN中的嵌套查询

,

如果您绝对需要JOIN语法,可以尝试以下查询

select 
    UserId,
    PrimaryRoleName=[0],
    SecondaryRoleName=[1]
from
(
    select 
        X.UserID,
        Name,
        SecondaryFl
    from 
        X_User_Role X 
    left join Role R
        on X.RoleID=R.RoleID
) src
pivot
(
    max(Name) for SecondaryFl in ([0],[1])
    )p

答案 3 :(得分:0)

返回动态数量的列?你正在寻找麻烦。

  • 如果用户有三个,四个,五个角色怎么办?

您应该返回角色,每行一个。一个简单的SQL连接就可以了。

答案 4 :(得分:0)

这是我在评论中提出的建议:

select xur.UserID, r1.Name as PrimaryRoleName, r2.Name as SecondaryRoleName
from X_User_Role xur 
JOIN Role r1
  ON r1.RoleID = xur.RoleID AND r1.SecondaryFl <> 1
JOIN Role r2
  ON r2.RoleID = xur.RoleID AND r2.SecondaryFl = 1
WHERE xur.UserID=1

答案 5 :(得分:0)

只是想发布另一个不诉诸GROUP BY的答案:

select x1.userid, r1.name, r2.name
  from x_user_role x1, role r1, x_user_role x2, role r2
  where r1.roleid = x1.roleid and r1.secondaryfl = 0 
    and x1.userid = 1
    and r2.roleid = x2.roleid and r2.secondaryfl = 1 
    and x2.userid = x1.userid