0

请查找示例数据:

h_company_id    company_nm      mainphone1      phone_cnt
20816          800 Flowers      5162377000         3
20816          800 Flowers      5162377131         1
20820         1st Source Corp.  5742353000         3
20821       1st United Bancorp  5613633400         2
20824         3D Systems Inc.   8033273900         4
20824         3D Systems Inc.   8033464010         1
11043         3I Group PLC      2079757115         1
11043         3I Group PLC      2079753731         15

期望的输出:

h_company_id    company_nm          mainphone1    phone_cnt  mainphone2    phone_cnt2
20816        800 Flowers    5162377000  3        5162377131        1
20820        1st Source Corp.   5742353000  3           NULL          NULL
20821        1st United Bancorp 5613633400  2           NULL          NULL
20824        3D Systems Inc.    8033273900  4        8033464010        1
11043        3I Group PLC   2079757115  1        2079753731        15

(上面在记事本/excel中复制)

嗨,大家好,

我想将列 mainphone1 的记录转置phone_cnt为新列mainphone2phone_cnt2以便列中的数据h_company_id应该是唯一的,这意味着应该只有一个条目h_company_id

提前致谢!

4

3 回答 3

3

从行到列的转换称为 PIVOT,在 SQL Server 中有几种不同的方法可以完成。

聚合/案例: 您可以将聚合函数与 CASE 表达式一起使用。这将通过将row_number()窗口函数应用于表中的数据来工作:

select h_company_id, company_nm,
  max(case when seq = 1 then mainphone1 end) mainphone1,
  max(case when seq = 1 then phone_cnt end) phone_cnt1,
  max(case when seq = 2 then mainphone1 end) mainphone2,
  max(case when seq = 2 then phone_cnt end) phone_cnt2
from
(
  select h_company_id, company_nm, mainphone1, phone_cnt,
    row_number() over(partition by h_company_id order by mainphone1) seq
  from yourtable
) d
group by h_company_id, company_nm;

请参阅SQL Fiddle with Demo。CASE 表达式检查序列号的值是 1 还是 2,然后将数据放入列中。

UNPIVOT / PIVOT: 由于您想要 PIVOT 存在于两列中的数据,那么您将需要先 UNPIVOTmainphone1phone_cnt列以将它们放在同一列中,然后应用 PIVOT 函数。

UNPIVOT 代码将类似于以下内容:

select h_company_id, company_nm,
  col+cast(seq as varchar(10)) col,
  value
from 
(
  select h_company_id, company_nm, 
    cast(mainphone1 as varchar(15)) mainphone,
    cast(phone_cnt as varchar(15)) phone_cnt,
    row_number() over(partition by h_company_id order by mainphone1) seq
  from yourtable
) d
unpivot
(
  value
  for col in (mainphone, phone_cnt)
) unpiv;

请参阅演示。此查询以下列格式获取数据:

| H_COMPANY_ID |         COMPANY_NM |        COL |      VALUE |
---------------------------------------------------------------
|        11043 |       3I Group PLC | mainphone1 | 2079753731 |
|        11043 |       3I Group PLC | phone_cnt1 |         15 |
|        11043 |       3I Group PLC | mainphone2 | 2079757115 |
|        11043 |       3I Group PLC | phone_cnt2 |          1 |
|        20816 |        800 Flowers | mainphone1 | 5162377000 |

然后将 PIVOT 函数应用于 中的值col

select h_company_id, company_nm, 
  mainphone1, phone_cnt1, mainphone2, phone_cnt2
from 
(
  select h_company_id, company_nm,
    col+cast(seq as varchar(10)) col,
    value
  from 
  (
    select h_company_id, company_nm, 
      cast(mainphone1 as varchar(15)) mainphone,
      cast(phone_cnt as varchar(15)) phone_cnt,
      row_number() over(partition by h_company_id order by mainphone1) seq
    from yourtable
  ) d
  unpivot
  (
    value
    for col in (mainphone, phone_cnt)
  ) unpiv
) src
pivot
(
  max(value)
  for col in (mainphone1, phone_cnt1, mainphone2, phone_cnt2)
) piv;

请参阅SQL Fiddle with Demo

多次加入:您还可以多次加入您的表以获得结果。

;with cte as
(
  select h_company_id, company_nm, mainphone1, phone_cnt,
    row_number() over(partition by h_company_id order by mainphone1) seq
  from yourtable
)
select c1.h_company_id,
  c1.company_nm,
  c1.mainphone1,
  c1.phone_cnt phone_cnt1,
  c2.mainphone1 mainphone2,
  c2.phone_cnt phone_cnt2
from cte c1
left join cte c2
  on c1.h_company_id = c2.h_company_id
  and c2.seq = 2
where c1.seq = 1;

请参阅SQL Fiddle with Demo

动态 SQL:最后,如果您有未知数量的值要转换,那么您将需要实现动态 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 h_company_id order by mainphone1) seq
                      from yourtable
                    ) d
                    cross apply
                    (
                      select 'mainphone', 1 union all
                      select 'phone_cnt', 2
                    ) c (col, so)
                    group by seq, so, col
                    order by seq, so
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


set @query = 'SELECT h_company_id, company_nm,' + @cols + ' 
              from 
             (
                select h_company_id, company_nm,
                  col+cast(seq as varchar(10)) col,
                  value
                from 
                (
                  select h_company_id, company_nm, 
                    cast(mainphone1 as varchar(15)) mainphone,
                    cast(phone_cnt as varchar(15)) phone_cnt,
                    row_number() over(partition by h_company_id order by mainphone1) seq
                  from yourtable
                ) d
                unpivot
                (
                  value
                  for col in (mainphone, phone_cnt)
                ) unpiv
            ) x
            pivot 
            (
                max(value)
                for col in (' + @cols + ')
            ) p '

execute(@query)

请参阅SQL Fiddle with Demo。都给出一个结果:

| H_COMPANY_ID |         COMPANY_NM | MAINPHONE1 | PHONE_CNT1 | MAINPHONE2 | PHONE_CNT2 |
-----------------------------------------------------------------------------------------
|        20820 |   1st Source Corp. | 5742353000 |          3 |     (null) |     (null) |
|        20821 | 1st United Bancorp | 5613633400 |          2 |     (null) |     (null) |
|        20824 |    3D Systems Inc. | 8033273900 |          4 | 8033464010 |          1 |
|        11043 |       3I Group PLC | 2079753731 |         15 | 2079757115 |          1 |
|        20816 |        800 Flowers | 5162377000 |          3 | 5162377131 |          1 |
于 2013-06-26T12:21:33.347 回答
0

以下可以工作(假设你的表被称为company):

SELECT
    c1.h_company_id,
    c1.company_nm,
    c1.mainphone1,
    c1.phone_cnt,
    c2.mainphone1 AS mainphone2,
    c2.phone_cnt AS phone_cnt2
FROM
    company AS c1
LEFT JOIN
    company AS c2 ON c2.h_company_id = c1.h_company_id

但是,为了尊重良好的做法,将数据分隔在两个表中不是更好吗?

  • company表格,有 2 列:(h_company_idPK)和company_nm
  • phone表格,有 4 列:( phone_idPK)、h_company_id(FK)mainphonephone_cnt

它将允许您在每个公司拥有任意数量的电话号码(包括没有)。

于 2013-06-26T09:18:37.597 回答
0

试试这个查询。这将帮助你

SELECT t.H_COMPANY_ID,t.COMPANY_NM, a.mainphone1,a.PHONE_CNT,b.mainphone1 mainphone2,b.PHONE_CNT PHONE_CNT2 FROM table_name t
INNER JOIN
(
   SELECT h_company_id,phone_cnt,mainphone1 FROM table_name
   WHERE mainphone1 
   IN(
       SELECT max(mainphone1) mainphone1 FROM table_name GROUP BY h_company_id
     )
)a ON t.H_COMPANY_ID = a.h_company_id
INNER JOIN
(
   SELECT h_company_id,phone_cnt,mainphone1 FROM table_name
   WHERE mainphone1 
   IN(
       SELECT min(mainphone1) mainphone1 from table_name GROUP BY h_company_id
     )
)b ON t.H_COMPANY_ID = b.H_COMPANY_ID 
GROUP BY t.H_COMPANY_ID,a.mainphone1,t.COMPANY_NM,a.PHONE_CNT,b.mainphone1,b.PHONE_CNT 
于 2013-06-26T10:49:04.253 回答