如何使用两个支点

How to use two pivot

我有 3 个表:

1) 用户

 id    name
 1     abc
 1     abc
 2      tyu
 2      tyu

2) phone

    id     number
     1     0987654
     1     0890764
     2     3445667
     2     5643456

3) 地址

id     addr  type
 1    usa    1
 1    uae    1 
 2    Uk     2

所以现在我写了下面的查询:

select * from (
              select u.id, u.name , p.number, cs.COL + CAST(row_number()over(PARTITION BY u.ID ORDER BY cs.COL) AS VARCHAR) RN ,
              cs1.COL + CAST(row_number()over(PARTITION BY a.ID ORDER BY cs1.COL) AS VARCHAR) RN1
               ,a.addr
              from user u left join phone p on p.id = u.id
              left join address as a on a.id = p.id CROSS APPLY (VALUES ('phone',number)) CS(Col,val)
                                                          CROSS APPLY (VALUES ('add',a.addr)) CS1(Col,val)
              where u.id=1 and a.type = '1'
              )P
    PIVOT (MAX(number) FOR RN IN ([phone1],[phone2])) as pivot1
    PIVOT (MAX(addr1)  FOR RN1 IN ([add1],[add2])) as pivot2

所以上面的查询给我的输出如下:

id  name    phone1      phone2      add1        add2
1   abc     NULL        0987654     NULL       usa
1   abc     0890764      NULL       uae         NULL   

但我想要如下输出:

  id    name    phone1      phone2      add1        add2
    1   abc     0890764     0987654     uae         usa

那么我怎样才能用枢轴实现这个呢?

在转置之前,您需要将数据设置为稍微不同的格式。 您的思路是正确的,但是将列 RN 和 RN1 合并为一个,然后 pvioting 同时对它们进行操作 - 如下所示。

select id, name, [phone1], [phone2], [add1], [add2]
from (
    select u.id, u.name, pa.columnname, pa.value from 
    user u inner join
    (
        select id, number as value, 'phone' + cast(row_number() over(partition by id order by number) as char(1)) as columnname
        from phone
        union all  
        select id, addr, 'add' + cast(row_number() over(partition by id order by addr) as char(1)) as columnname
        from address where type = 1
    ) as pa
        on pa.id = u.id
    ) as base
pivot (max(value) for columnname in ([phone1], [phone2], [add1], [add2])) p
where id = 1;
declare @user TABLE 
    (id int, name varchar(3))
;    
INSERT INTO @user
    (id, name)
VALUES
    (1, 'abc'),
    (1, 'abc'),
    (2, 'tyu'),
    (2, 'tyu')
    ;
declare @phone  TABLE 
    (id int, number int)
;   
INSERT INTO @phone
    (id, number)
VALUES
    (1, 0987654),
    (1, 0890764),
    (2, 3445667),
    (2, 5643456)
;
declare @address TABLE 
    (id int, addr varchar(3), type int)
;  
INSERT INTO @address
    (id, addr, type)
VALUES
    (1, 'usa', 1),
    (1, 'uae', 1),
    (2, 'Uk', 2)
;

select id,name,MAX(phone1)phone1,max(phone2)phone2,max(add1)add1,max(add2)add2 from (
              select u.id, u.name , p.number, cs.COL + CAST(row_number()over(PARTITION BY u.ID ORDER BY cs.COL) AS VARCHAR) RN ,
              cs1.COL + CAST(row_number()over(PARTITION BY a.ID ORDER BY cs1.COL) AS VARCHAR) RN1
               ,a.addr
              from @user u left join @phone p on p.id = u.id
              left join @address as a on a.id = p.id CROSS APPLY (VALUES ('phone',number)) CS(Col,val)
                                                          CROSS APPLY (VALUES ('add',a.addr)) CS1(Col,val)
              where u.id=1 and a.type = '1'
              )P
    PIVOT (MAX(number) FOR RN IN ([phone1],[phone2])) as pivot1
    PIVOT (MAX(addr)  FOR RN1 IN ([add1],[add2])) as pivot2
    group by id,name