gpt4 book ai didi

sql - TSQL - 父子(1 到零/多)分组/聚合

转载 作者:行者123 更新时间:2023-12-02 09:04:45 25 4
gpt4 key购买 nike

代码(示例数据暂存):

DECLARE @Emp TABLE
(
[EId] INT IDENTITY(1, 1)
, [FN] NVARCHAR(50)
, [LN] NVARCHAR(50)
) ;
DECLARE @EmpPhCont TABLE
(
[EId] INT
, [PhType] VARCHAR(10)
, [PhNum] VARCHAR(16)
, [PhExt] VARCHAR(10)
, [IsMain] BIT
, [CreatedOn] DATETIME
) ;

INSERT INTO @Emp
VALUES
( N'Emp1', N'Emp1' )
, ( N'Emp2', N'Emp2' )
, ( N'Emp3', N'Emp3' )
, ( N'Emp4', N'Emp4' )
, ( N'Emp5', N'Emp5' )
, ( N'Emp6', N'Emp5' ) ;

INSERT INTO @EmpPhCont
VALUES
( 1, 'Home', '111111111', NULL, 0, '2020-01-01 00:00:01' )
, ( 1, 'Mobile', '222222222', NULL, 1, '2020-01-01 00:00:02' )
, ( 1, 'Work', '333333333', NULL, 0, '2020-01-01 00:00:03' )

, ( 2, 'Work', '444444444', '567', 1, '2020-01-01 00:00:04' )
, ( 2, 'Mobile', '555555555', NULL, 0, '2020-01-01 00:00:05' )
, ( 2, 'Mobile', '454545454', NULL, 0, '2020-01-01 00:00:06' )

, ( 3, 'Home', '777777777', NULL, 0, '2020-01-01 00:00:07' )
, ( 3, 'Mobile', '888888888', NULL, 1, '2020-01-01 00:00:08' )
, ( 3, 'Mobile', '12121212', NULL, 0, '2020-01-01 00:00:09' )

, ( 4, 'Work', '101010101', '111', 1, '2020-01-01 00:00:10' )
, ( 4, 'Work', '101010102', '232', 0, '2020-01-01 00:00:11' )

, ( 5, 'Work', '545454545', '456', 0, '2020-01-01 00:00:10' )
, ( 5, 'Work', '456456456', NULL, 1, '2020-01-01 00:00:11' ) ;

描述:

@Emp 是示例员工表(唯一员工记录)。

  • EId = 员工 ID
  • FN = 名字
  • LN = 姓氏

@EmpPhCont 是示例员工电话联系人表(@Emp 表中的每个 Emp 在此可以有零个、一个或多个电话号码 - 根据 Emp/Type 是唯一的)。

  • PhType = 电话类型(家庭电话、移动电话、工作电话等)
  • PhNum = 电话号码
  • PhExt = 电话分机(主要适用于“工作”PhType)
  • IsMain = 是否是主要联系电话。每个拥有电话号码的员工都会有 1 条标记为 IsMain 的记录。
  • CreatedOn = 创建记录的日期

目标:

使用以下列为每个员工输出 1 条记录

EId | HomeNum | MobileNum | WorkNum | WorkNumExt | MainPhType

规则:

返回来自 @Emp 的所有记录的所有 EId,无论它们是否有 @EmpPhCont 记录。

对于每个具有 @EmpPhCont 记录可用的 emp,返回相应 PhType 的最新创建的 PhNum 和 PhExt,除非同一 Emp/PhType 的较旧记录被标记为 IsMain = 1(对于任何 emp,对于任何 PhType,如果 IsMain = 1,则始终返回该 PhNum 和 PhExt 值)。

预期输出:

EId HomeNum     MobileNum   WorkNum     WorkNumExt  MainPhType
1 111111111 222222222 333333333 NULL Mobile
2 NULL 454545454 444444444 567 Work
3 777777777 888888888 NULL NULL Mobile
4 NULL NULL 101010102 111 Work
5 NULL NULL 456456456 NULL Work
6 NULL NULL NULL NULL NULL

我不成功的尝试:

SELECT      [EM].[EId]
, MAX ( IIF([PH].[PhType] = 'Home', [PH].[PhNum], NULL)) AS [HomePhNum]
, MAX ( IIF([PH].[PhType] = 'Mobile', [PH].[PhNum], NULL)) AS [MobilePhNum]
, MAX ( IIF([PH].[PhType] = 'Work', [PH].[PhNum], NULL)) AS [WorkPhNum]
FROM @Emp AS [EM]
LEFT JOIN @EmpPhCont AS [PH]
ON [EM].[EId] = [PH].[EId]
GROUP BY [EM].[EId] ;

最佳答案

CTE 内使用 ROW_NUMBER() 窗口函数从 @EmpPhCont 获取您想要返回的行并加入此 CTE@Emp:

with cte as (
select *,
row_number() over (partition by [EId], [PhType] order by [IsMain] desc, [CreatedOn] desc) rn
from @EmpPhCont
)
select e.[EId],
max(case when c.[PhType] = 'Home' then c.[PhNum] end) HomeNum,
max(case when c.[PhType] = 'Mobile' then c.[PhNum] end) MobileNum,
max(case when c.[PhType] = 'Work' then c.[PhNum] end) WorkNum,
max(case when c.[PhType] = 'Work' then c.[PhExt] end) WorkNumExt,
max(case when c.[IsMain] = 1 then c.[PhType] end) MainPhType
from @Emp e left join cte c
on c.[EId] = e.[EId] and c.rn = 1
group by e.[EId]

参见 demo
结果:

> EId | HomeNum   | MobileNum | WorkNum   | WorkNumExt | MainPhType
> --: | :-------- | :-------- | :-------- | :--------- | :---------
> 1 | 111111111 | 222222222 | 333333333 | null | Mobile
> 2 | null | 454545454 | 444444444 | 567 | Work
> 3 | 777777777 | 888888888 | null | null | Mobile
> 4 | null | null | 101010101 | 111 | Work
> 5 | null | null | 456456456 | null | Work
> 6 | null | null | null | null | null

关于sql - TSQL - 父子(1 到零/多)分组/聚合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59902837/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com