sql - SQL 透视多列

标签 sql sql-server t-sql sql-server-2014

代码:

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 非主要电话号码及其电话类型。我可以获得最多的主要/非主要电话号码,但需要以某种方式获取他们的电话类型。我不想根据 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

最佳答案

似乎您需要两次申请:

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,那么您可以使用临时表,只需转储具有相关索引的联系人

#temp (Employee_Id, IsMainNumber) include (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;

关于sql - SQL 透视多列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51408030/

相关文章:

php - 在 PHP 中使用外键将行插入表中

php - 检查两个 MySQL 表中是否存在值

sql-server - 适用于 Amazon RDS 的 SQL Server 报告服务

sql - 使用 SQL 在每第 n 次出现分隔符后将字符串拆分为单独的列,并根据需要添加默认值

java - Netbeans SQL 编辑器问题

sql - 外连接的固定条件

sql-server - 提高数据库性能最快的方法是什么?直接瞄准我的目标(5000 个用户)?或者首先使用人工里程碑?

c# - 在 ASP.NET C# 中使用未知数量的值查询 SQL 数据库

t-sql - 如何使用 tSQLt 测试更新表(相对于返回结果集)的 SQL 存储过程

c# - 使用 LINQ 将数据插入到使用序列作为主键生成器的表中