所需形式的T-SQL形状表

时间:2013-02-05 11:30:17

标签: sql tsql pivot

我有两个表:TableA和TableB

TableA:columnBLA,objName,objID

TableB:objID,ColumnIndex,StringValue,NumberValue,DateValue

TableA has a row: bla, Object Name, 21

TableB also has data for objID=21:

21, 1, a, NULL, NULL
21, 1, b, NULL, NULL
21, 1, c, NULL, NULL
21, 2, NULL, 11, NULL
21, 2, NULL, 22, NULL
21, 2, NULL, 33, NULL
21, 3, NULL, NULL, 1/1/2012
21, 3, NULL, NULL, 1/1/2013
21, 3, NULL, NULL, 1/1/2014

现在我想将这些数据重新整形为以下形式:

a, 11, 1/1/2012
b, 22, 1/1/2013
c, 33, 1/1/2014

我到目前为止:

Select StringValue, NumberValue, DateValue
From
(Select StringValue
From TableA ta WITH (NOLOCK), TableB tb WITH (NOLOCK)
WHERE ta.objID = tb.objID
AND t.objName = N'Object Name'
AND d.ColumnIndex = 1) As StringValues
,
(Select NumberValue
From TableA ta WITH (NOLOCK), TableB tb WITH (NOLOCK)
WHERE ta.objID = tb.objID
AND t.objName = N'Object Name'
AND d.ColumnIndex = 2) As NumberValues
,
(Select DateValue
From TableA ta WITH (NOLOCK), TableB tb WITH (NOLOCK)
WHERE ta.objID = tb.objID
AND t.objName = N'Object Name'
AND d.ColumnIndex = 1) As DateValues

但是我得到了不必要的结果。 有人告诉我,我应该使用PIVOT,但我的SQL知识并没有跨越那么远。

2 个答案:

答案 0 :(得分:1)

以下是使用UNPIVOTPIVOT执行此操作的一种方法:

select objid, stringvalue, numbervalue, datevalue
from
(
  select objid, col, value,
    row_number() over(partition by objid, col order by value) rn
  from
  (
    select a.objid,
      b.stringvalue,
      b.numbervalue,
      b.datevalue
    from tablea a
    left join tableb b
      on a.objid = b.objid
  ) src
  unpivot
  (
    value
    for col in (stringvalue, numbervalue, datevalue)
  ) unpiv
) s
pivot
(
  max(value)
  for col in (stringvalue, numbervalue, datevalue)
) piv

SQL Fiddle with Demo unpivot 从单独的列中获取值并将其转换为行。然后,我将row_number()应用于数据,然后应用 pivot 将其重新转换为列。

在不使用PIVOTUNPIVOT函数的情况下执行此操作的另一种方法是应用row_number(),然后使用带有CASE表达式的聚合函数:

select objid,
  max(case when columnindex = 1 then stringvalue end) stringvalue,
  max(case when columnindex = 2 then numbervalue end) numbervalue,
  max(case when columnindex = 3 then datevalue end) datevalue
from
(
  select a.objid,
    b.stringvalue,
    b.numbervalue,
    b.datevalue,
    b.columnindex,
    row_number() over(partition by a.objid, b.columnindex 
                      order by b.columnindex) rn
  from tablea a
  left join tableb b
    on a.objid = b.objid
) src
group by objid, rn

请参阅SQL Fiddle with Demo

两个查询的结果是:

| OBJID | STRINGVALUE | NUMBERVALUE | DATEVALUE |
-------------------------------------------------
|    21 |           a |          11 |  1/1/2012 |
|    21 |           b |          22 |  1/1/2013 |
|    21 |           c |          33 |  1/1/2014 |

答案 1 :(得分:0)

使用CTErow_number()Fiddle Demo

;with cte as (
  select row_number() over (partition by columnIndex 
                            order by StringValue, NumberValue, DateValue) rn,
  StringValue, NumberValue, DateValue
  from tableB tb join tableA ta on tb.objId = ta.objid
)
select t1.StringValue, t2.NumberValue, t3.DateValue
from cte t1 join cte t2 on t1.rn = t2.rn 
            join cte t3 on t1.rn = t3.rn 
where not (t1.stringValue is null or t2.numberValue is null or t3.datevalue is null)
order by t1.stringValue