T-SQL左连接两次

时间:2017-11-08 13:44:23

标签: sql-server tsql left-join

下面的查询按计划工作,它显示我加入它的方式,这很好,但问题是,如果你有更多的“专业化”表用于用户,像“邮件类型”或任何东西用户可以拥有多个数据...您必须为每个数据进行两次左连接,并"give priority"通过ISNULL(在这种情况下)

我想知道,我怎么能避免使用两个连接,并在单个连接中“优先”TypeId 2优先于TypeId 1,这是否可能?

if object_id('tempdb..#Tab1') is not null drop table #Tab1
create table #Tab1 (UserId int, TypeId int)
if object_id('tempdb..#Tab2') is not null drop table #Tab2
create table #Tab2 (TypeId int, TypeDescription nvarchar(50))

insert into #Tab1 (UserId, TypeId)
values
(1, 1),
(1, 2)
insert into #Tab2 (TypeId, TypeDescription)
values
(1, 'User'),
(2, 'Admin')

select *, ISNULL(t2.TypeDescription, t3.TypeDescription) [Role]
from #Tab1 t1
    LEFT JOIN #Tab2 t2 on t1.TypeId = t2.TypeId and
                          t2.TypeId = 2
    LEFT JOIN #Tab2 t3 on t1.TypeId = t3.TypeId and
                          t3.TypeId = 1

2 个答案:

答案 0 :(得分:3)

第一个问题是确定优先级。在这种情况下,您可以使用最大的TypeId,但这似乎不是一个好主意。您可以添加另一列作为优先序号。

从那里开始,它是每组查询的前1名:

使用top with tiesrow_number()

select top 1 with ties
    t1.UserId, t1.TypeId, t2.TypeDescription
from #Tab1 t1
  left join #Tab2 t2
    on t1.TypeId = t2.TypeId
order by row_number() over (
      partition by t1.UserId 
      order by t2.Ordinal
      --order by t1.TypeId desc
)

使用common table expressionrow_number()

;with cte as (
select t1.UserId, t1.TypeId, t2.TypeDescription
  , rn = row_number() over (
      partition by t1.UserId 
      order by t2.Ordinal
      --order by t1.TypeId desc
    )
from #Tab1 t1
  left join #Tab2 t2
    on t1.TypeId = t2.TypeId
)
select UserId, TypeId, TypeDescription
from cte
where rn = 1

两者的rextester演示:http://rextester.com/KQAV36173

都返回:

+--------+--------+-----------------+
| UserId | TypeId | TypeDescription |
+--------+--------+-----------------+
|      1 |      2 | Admin           |
+--------+--------+-----------------+

答案 1 :(得分:0)

实际上我根本不认为你根本不需要加入。但是你必须采用最大TypeID而不考虑TypeDescription,因为这些差异可能会击败Group By。因此,解决方法是最初使用Max而不使用TypeDescription,然后子查询结果以获取TypeDescription。

SELECT dT.*
      ,(SELECT TypeDescription FROM #Tab2 T2 WHERE T2.TypeId = dT.TypeId) [Role] --2. Subqueries TypeDescription using the Max TypeID
  FROM (
         select t1.UserId
               ,MAX(T1.TypeId) [TypeId] 
                --, T1.TypeDescription AS [Role] --1. differences will defeat group by. Subquery for value later in receiving query.
          from #Tab1 t1                
         GROUP BY t1.UserId
       ) AS dT

生成输出:

UserId  TypeId  Role
1       2       Admin