联接两个表,如果第一个表的值为空,但第二个表具有值,则取第二个表的值

时间:2018-07-24 09:51:37

标签: sql sql-server tsql

我有用户和组。可以授予他们每个人在表上执行某项操作的权限(例如“ SELECT”,“ INSERT”等)。现在,我想创建一个包含用户名及其权限的表。

  • 因此,如果用户对SELECT形式的tableA没有特定的权限,但是他在IT组中,则该IT组对此{{1}拥有SELECT的权限},他对tableA的许可应为tableA,而不是SELECT

  • 用户应具有多个权限。

  • 如果用户拥有至少一项权利(无论是特定于用户还是组),则应显示所有权利

  • 如果用户没有权限,则应显示NULL

这是我的示例表:

  • NULL属于NO组,并且获得了MEWO\STFL的特定权限
  • select/insertMEWO\GEIM组中,并获得对IT的特定权限
  • insertMEWO\WAD组中,并获得对IT的特定权限
  • selectMEWO\OZF组中,但没有特定的权限
  • IT不是MEWO\BIA组,也没有特定的权限
  • IT是一个群组,并获得了IT
  • 的权限

表1(单用户许可)

table1

表2(具有组权限的组成员)

table2

预期产量

一个带有以下输入的表:

  • select与表1相同
  • MEWO\STFLMEWO\GEIM
  • insert/select与表1相同
  • MEWO\WAD具有MEWO\OZF INSTEAD
  • selectMEWO\BIA
  

UNION 这两个表已经使我关闭,但是有重复项。

3 个答案:

答案 0 :(得分:3)

您可以使用coalesce()函数:

select coalesce(t1.permission_name, t2.permission_name) as permission_name ,
       t1.name
from table2 t2 left join
     table1 t1
     on t1.name = t2.username;

对于您当前的尝试,我没有发现任何P好感。

编辑:也许您需要FULL OUTER JOIN,但您的预期输出并不表明这一点。

select coalesce(t1.permission_name, t2.permission_name) as permission_name ,
           t1.name
from table1 t1 full outer join
     table2 t2
     on t1.name = t2.username;

编辑::我想您需要row_number函数:

with t as (
     select permission_name, name
     from table1
     union all
     select permission_name, username
     from table1
)   

select top (1) with ties *
from t
order by row_number() over (partition by name, permission_name order by name);

答案 1 :(得分:1)

这是经过修改的查询,用于捕获您要查找的内容。

DECLARE @TABLE1 TABLE(PermissionName varchar(20), DName varchar(20))
INSERT INTO @TABLE1
SELECT 'INSERT', 'MEWO\STFL' UNION ALL
SELECT 'SELECT', 'MEWO\STFL' UNION ALL
SELECT  NULL, 'MEWO\BIA' UNION ALL
SELECT 'SELECT', 'MEWO\WAD' UNION ALL
SELECT 'INSERT', 'MEWO\GEIM' UNION ALL
SELECT NULL, 'MEWO\OZF' 



DECLARE @TABLE2 TABLE(PermissionName varchar(20), UserName varchar(20))
INSERT INTO @TABLE2
SELECT 'SELECT', 'MEWO\WAD' UNION ALL
SELECT 'SELECT', 'MEWO\GEIM' UNION ALL
SELECT 'SELECT', 'MEWO\OZF' 



;with Permission as
(
SELECT DName,  PermissionName, RowNum=ROW_NUMBER()over(PARTITION BY DName ORDER BY LEN(PermissionName) DESC)

        FROM 
        (
            select * from @TABLE1
            union 
            select * from @TABLE2
        )g

)




SELECT  
    PM.DName, 
    PC1.PermissionName+
    CASE WHEN PC2.PermissionName IS NOT NULL  THEN '/'+PC2.PermissionName
    ELSE ''
    END
from
 (SELECT DISTINCT DName FROM Permission) PM

 LEFT JOIN Permission PC1 ON
    PC1.DName=PM.DName
    AND
    PC1.RowNum=1

 LEFT JOIN Permission PC2 ON  ---depending on the number of permissions you might have to add more joins
    PC2.DName=PM.DName
    AND
    PC2.RowNum=2
 order by
 1

以下结果:enter image description here

答案 2 :(得分:0)

我想这可以满足您的条件:

SELECT
    permission_name
    , name
FROM
    (
    SELECT
        coalesce(t2.permission_name, t1.permission_name) as permission_name
        , t1.name AS name
    FROM 
        table1
        LEFT JOIN table2
            ON t1.name = t2.username
    ) AS _temp
WHERE
    NOT _temp.permission_name IS NULL

我假设您不希望其中t1.permission_name为null且t2.permission_name也为NULL或什至t2没有该条目的行的行-因此,外部查询(_temp)。如果不需要,只需完全删除外部查询即可。