代码:
DECLARE @Employee TABLE
(
[Employee_Id] INT IDENTITY(1, 1)
, [Code] NVARCHAR(10)
) ;
INSERT INTO @Employee
VALUES ( N'E1' ), ( N'E2' ), ( N'E3' ) ;
DECLARE @Contact TABLE
(
[Employee_Id] INT
, [PhoneType] CHAR(1)
, [PhoneNumber] VARCHAR(20)
, [IsMainNumber] BIT
) ;
INSERT INTO @Contact
VALUES (1, 'M', '1234567890', 1), (1, 'H', '1234567891', 0),
(1, 'M', '1234567892', 0), (1, 'B', '1234567893', 0),
(2, 'M', '2234567890', 0), (2, 'H', '2234567891', 1),
(2, 'B', '2234567892', 0), (2, 'M', '2234567893', 0),
(3, 'M', '3234567890', 0), (3, 'H', '3234567891', 0),
(3, 'M', '3234567892', 0), (3, 'B', '3234567893', 1);
SELECT
[E].[Employee_Id],
[E].[Code],
[COA].[MainPhoneNumber],
[COA].[NonMainNumber]
FROM
@Employee AS [E]
OUTER APPLY
(SELECT
MAX (IIF([C].[IsMainNumber] = 1, [C].[PhoneNumber], NULL)) [MainPhoneNumber],
MAX (IIF([C].[IsMainNumber] = 0, [C].[PhoneNumber], NULL)) [NonMainNumber]
FROM
@Contact AS [C]
WHERE
[E].[Employee_Id] = [C].[Employee_Id]
GROUP BY
[C].[Employee_Id]) AS [COA] ;
当前输出
Employee_Id Code MainPhoneNumber NonMainNumber
1 E1 1234567890 1234567893
2 E2 2234567891 2234567893
3 E3 3234567893 3234567892
目标
我需要返回MAX主要电话号码及其电话类型和MAX非主要电话号码及其电话类型。我可以获取MAX主要/非主要电话号码,但需要以某种方式获取其电话类型。我不想基于Employee_Id和PhoneNumber进行两个额外的联接并获取类型,因为原始表很大并且会减慢很多速度。试图找出性能良好的替代方案。
所需的输出
Employee_Id Code MainPhoneType MainPhoneNumber NonMainPhoneType NonMainNumber
1 E1 M 1234567890 B 1234567893
2 E2 H 2234567891 M 2234567893
3 E3 B 3234567893 M 3234567892
答案 0 :(得分:1)
似乎您需要两个apply
:
select e.Employee_Id, e.Code,
c.PhoneType as MainPhoneType, c.PhoneNumber as MainPhoneNumber,
c1.PhoneType as NonMainPhoneType, c1.PhoneNumber as NonMainNumber
from @Employee e outer apply
(select top (1) c.PhoneType, c.PhoneNumber
from @Contact c
where c.Employee_Id = e.Employee_Id and
c.IsMainNumber = 1
order by c.phonetype
) c outer apply
(select top (1) c1.PhoneType, c1.PhoneNumber
from @Contact c1
where c1.Employee_Id = e.Employee_Id and
c1.IsMainNumber = 0
order by c1.phonetype
) c1;
如果您不想两次执行JOIN
,则可以使用临时表,只需转储具有相关index
的联系人
#temp(Employee_Id,IsMainNumber)包括(PhoneType,PhoneNumber)
insert into #temp (Employee_Id, PhoneType, PhoneNumber, IsMainNumber)
select Employee_Id, PhoneType, PhoneNumber, IsMainNumber
from (select *, row_number() over (partition by Employee_Id, IsMainNumber order by PhoneType) as seq
from @Contact
) c
where seq = 1
现在,您无需再次使用@Contact
:
select e.*, m.*
from @Employee e cross apply
(select max(case when t.IsMainNumber = 1 then t.PhoneType end) as MainPhoneType,
max(case when t.IsMainNumber = 1 then t.PhoneNumber end) as MainPhoneNumber,
max(case when t.IsMainNumber = 0 then t.PhoneType end) as NonMainPhoneType,
max(case when t.IsMainNumber = 0 then t.PhoneNumber end) as NonMainNumber
from #temp t
where t.Employee_Id = e.Employee_Id
) m;
答案 1 :(得分:1)
不太确定如何确定所需的nonMainNumber。似乎大多数示例数据都有几行可以返回。我将把这项工作留给您。这是您可以为此使用一些条件聚合的方法。
select x.Employee_Id
, x.Code
, MainPhoneType = max(case when x.RowNum = 1 then x.PhoneType end)
, MainPhoneNumber = max(case when x.RowNum = 1 then x.PhoneNumber end)
, NonMainPhoneType = max(case when x.RowNum = 2 then x.PhoneType end)
, NonMainPhoneNumber = max(case when x.RowNum = 2 then x.PhoneNumber end)
from
(
select e.Employee_Id
, e.Code
, c.PhoneType
, c.PhoneNumber
, RowNum = ROW_NUMBER() over(partition by e.Employee_Id order by c.IsMainNumber desc, c.PhoneType) --Not sure how you determine the non MainNumber when there are several to pick from
from @Employee e
join @Contact c on c.Employee_Id = e.Employee_Id
) x
group by x.Employee_Id
, x.Code
答案 2 :(得分:1)
您可以通过条件聚合来做到这一点:
select e.Employee_Id, e.Code
max(case when seqnum = 1 and c.PhoneType = 'M' then c.PhoneType end) as MainPhoneType
max(case when seqnum = 1 and c.PhoneType = 'M' then x.PhoneNumber end) as MainPhoneNumber,
max(case when seqnum = 1 and c.PhoneType <> 'M' then c.PhoneType end) as NonMainPhoneType
max(case when seqnum = 1 and c.PhoneType <> 'M' then c.PhoneNumber end) as NonMainPhoneNumber
from @Employee e join
(select c.*,
row_number() over (partition by c.Employee_Id
(case when PhoneType = 'M' then 'M' end)
order by c.PhoneNumber desc
) as seqnum
from @Contact c
) c
on c.Employee_Id = e.Employee_Id
group by e.Employee_Id, e.Code;
此逻辑中的关键思想是partition by
子句。它将两种类型的电话分为两组-'M'
代表“主要”,NULL
代表其他所有。