从第二行中选择列,按ID添加到sql组中第一行的末尾

时间:2013-06-24 11:08:44

标签: sql sql-server sql-server-2008 tsql

我在数据库中有一个表客户,如下所示。

ID  UID  Address1  Name  code
10  5    A         Jac   683501
11  5    B         Joe   727272
13  6    C         mat   373737

前两个记录(10,11)有一个共同的uID -5。这两个记录可以视为一个单元。 第四条记录有一个单独的UID,因此它是一个单独的单元

我需要在csv文件中生成一个输出

ID  UID Name  code     Address1  Name2  Code2
10  5   jac   683501   A         Joe    727272 
13  6   mat   373737   C 

Name2和code2值来自第二行,因为前两条记录的UID相同,我们可以将其视为一个单元。

任何人都可以提供查询以生成这些记录的提示。

2 个答案:

答案 0 :(得分:2)

将数据从行转换为列的过程称为PIVOT。有几种方法可以做到这一点。

您可以使用row_number()以及带有CASE表达式的聚合函数:

select min(id),
  uid,
  max(case when seq = 1 then name end) Name,
  max(case when seq = 1 then code end) Code,
  max(case when seq = 1 then Address1 end) Address1,
  max(case when seq = 2 then name end) Name2,
  max(case when seq = 2 then code end) code2,
  max(case when seq = 2 then Address1 end) Address1_2
from
(
  select id, uid, address1, name, code,
    row_number() over(partition by uid order by id) seq
  from yourtable
) d
group by uid;

请参阅SQL Fiddle with Demo

您可以同时使用UNPIVOT和PIVOT功能:

select id, uid,
  name1, code1, address1, name2, code2, address2
from 
(
  select id, uid, col+cast(seq as varchar(10)) col, value
  from
  (
    select 
      (select min(id) 
       from yourtable t2
       where t.uid = t2.uid) id, 
      uid, 
      cast(address1 as varchar(20)) address, 
      cast(name as varchar(20)) name, 
      cast(code as varchar(20)) code,
      row_number() over(partition by uid order by id) seq
    from yourtable t
  ) d
  unpivot
  (
    value
    for col in (address, name, code)
  ) unpiv
) src
pivot
(
  max(value)
  for col in (name1, code1, address1, name2, code2, address2)
) piv;

请参阅SQL Fiddle with Demo

最后,如果每个uid都有未知数量的值,那么您可以使用动态SQL来获得结果:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT ',' + QUOTENAME(col+(cast(seq as varchar(10)))) 
                    from
                    (
                      select row_number() over(partition by uid order by id) seq
                      from yourtable
                    ) d
                    cross apply
                    (
                      select 'name', 1 union all
                      select 'code', 2 union all
                      select 'address', 3 
                    ) c (col, so)
                    group by seq, col, so
                    order by seq, so
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT id, uid,' + @cols + ' 
            from 
            (
                select id, uid, col+cast(seq as varchar(10)) col, value
                from
                (
                  select 
                    (select min(id) 
                     from yourtable t2
                     where t.uid = t2.uid) id, 
                    uid, 
                    cast(address1 as varchar(20)) address, 
                    cast(name as varchar(20)) name, 
                    cast(code as varchar(20)) code,
                    row_number() over(partition by uid order by id) seq
                  from yourtable t
                ) d
                unpivot
                (
                  value
                  for col in (address, name, code)
                ) unpiv
            ) x
            pivot 
            (
                max(value)
                for col in (' + @cols + ')
            ) p '

execute(@query);

SQL Fiddle with Demo。所有版本都会给出结果:

| ID | UID | NAME1 |  CODE1 | ADDRESS1 |  NAME2 |  CODE2 | ADDRESS2 |
---------------------------------------------------------------------
| 10 |   5 |   Jac | 683501 |        A |    Joe | 727272 |        B |
| 13 |   6 |   mat | 373737 |        C | (null) | (null) |   (null) |

答案 1 :(得分:1)

尝试内部联接。

select u2.firstname,u2.col2,
from users u
inner join users u2 on u.userid=u2.userid
where u.firstname=u2.lastname