【问题标题】:Can anyone write query for this?任何人都可以为此编写查询吗?
【发布时间】:2013-04-23 06:05:04
【问题描述】:

我的表如下

recordId    fwildcardId refNumber   wildcardName    wildcardValue   comments
404450  154834               2              aaa               p          p
404450  154833               1              aa                oi         p   
406115  154867               1              98                ff        ff
406199  154869               1              aa                aaaa      ssss
406212  154880               1              bbbbb             card      comm

我需要输出为

      RecordId fwildcardid1 refNo1  Name1  Value1 comments1 fwildcardid2 refNo2 Name2 Value2 comments2 fwildcardid3 refNo3 Name3 Value3 comments3 
         404450  154834         2     aaa     p      p        154833       1     aa    oi        p 
         406115   Null         Null   Null   Null   Null      Null        Null   Null   Null   Null   154867        1     98       ff       ff
         406199   Null         Null   Null   Null    Null    154869       1      aa    aaaa     ssss      Null      Null     Null    Null   

我尝试像下面这样旋转,但没有成功。

select t1.recordId,t1.wildcardid as fwildcardId,t1.refNo as refNumber,t2.wildcardName,t1.attributeValue as wildcardValue,t1.comments 
into #tempp
from fwildcards t1
inner join fwildcardattributes t2 on t2.WildcardID=t1.attributenameid and t2.MarketID=5
inner join fitems t3 on t3.recordid=t1.recordid and t3.marketid=5
order by recordid,attributenameid


select * from #tempp
pivot (min (wildcardValue) for wildcardName in ([aaa],[aa],[aaaa],[98],[kki],[bbbbb],[SUN])) as wildcardValuePivot

【问题讨论】:

标签: sql sql-server sql-server-2008-r2 pivot unpivot


【解决方案1】:

为了获得此结果,您必须先对数据进行 UNPIVOT 并进行 PIVOT。 UNPIVOT 将获取 fwildcardIdrefNumberwildcardNamewildcardValuecomments 列中的值并将它们转换为行。一旦数据成行,您就可以应用 PIVOT 函数来获得最终结果。

要取消透视数据,您可以使用 UNPIVOT 函数或使用 CROSS APPLY 和 VALUES 子句。

反透视

select recordid,
  col+cast(rn as varchar(10)) col,
  unpiv_value
from
(
  select recordid,
    cast(fwildcardid as varchar(10)) fwildcardid,
    cast(refnumber as varchar(10)) refnumber,
    cast(wildcardname as varchar(10)) name,
    cast(wildcardvalue as varchar(10)) value,
    cast(comments as varchar(10)) comments,
    row_number() over(partition by recordid
                      order by fwildcardid) rn
  from tempp
) d
unpivot
(
  unpiv_value
  for col in (fwildcardid, refnumber, name, value, comments)
) c 

SQL Fiddle with Demo

交叉应用和值:

select recordid,
  col+cast(rn as varchar(10)) col,
  value
from
(
  select recordid,
    cast(fwildcardid as varchar(10)) fwildcardid,
    cast(refnumber as varchar(10)) refnumber,
    wildcardname,
    wildcardvalue,
    comments,
    row_number() over(partition by recordid
                      order by fwildcardid) rn
  from tempp
) d
cross apply
(
  values
    ('fwildcardid', fwildcardid),
    ('refnumber', refnumber),
    ('name', wildcardname),
    ('value', wildcardvalue),
    ('comments', comments)
) c (col, value)

SQL Fiddle with Demo

这些将结果转换为一种格式:

| RECORDID |          COL |  VALUE |
------------------------------------
|   404450 | fwildcardid1 | 154833 |
|   404450 |   refnumber1 |      1 |
|   404450 |        name1 |     aa |
|   404450 |       value1 |     oi |
|   404450 |    comments1 |      p |
|   404450 | fwildcardid2 | 154834 |

当您将数据反透视到同一列时,它必须是相同的数据类型。您会注意到我对列应用了cast,因此数据类型是相同的。

一旦数据为行格式,您可以使用 PIVOT 将其转换回列:

select *
from
(
  select recordid,
    col+cast(rn as varchar(10)) col,
    unpiv_value
  from
  (
    select recordid,
      cast(fwildcardid as varchar(10)) fwildcardid,
      cast(refnumber as varchar(10)) refnumber,
      cast(wildcardname as varchar(10)) name,
      cast(wildcardvalue as varchar(10)) value,
      cast(comments as varchar(10)) comments,
      row_number() over(partition by recordid
                        order by fwildcardid) rn
    from tempp
  ) d
  unpivot
  (
    unpiv_value
    for col in (fwildcardid, refnumber, name, value, comments)
  ) c 
) src
pivot
(
  max(unpiv_value)
  for col in (fwildcardid1, refnumber1, name1, value1, comments1,
              fwildcardid2, refnumber2, name2, value2, comments2)
) piv;

SQL Fiddle with Demo

如果你有已知数量的列,上面的版本效果很好,但是如果你有未知数量的值将被转换成列,那么你将需要使用动态 sql 来获取结果:

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

select @cols = STUFF((SELECT  ',' + QUOTENAME(c.col+cast(rn as varchar(10))) 
                    from
                    (
                      select row_number() over(partition by recordid
                                                order by fwildcardid) rn
                      from tempp
                    ) t
                    cross apply
                    (
                      select 'fwildcardid' col, 1 sortorder union all
                      select 'refNumber', 2 union all
                      select 'name', 3 union all
                      select 'value', 4 union all
                      select 'comments', 5
                    ) c 
                    group by col, rn, sortorder
                    order by rn, sortorder
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT recordid,' + @cols + ' from 
            (
              select recordid,
                col+cast(rn as varchar(10)) col,
                unpiv_value
              from
              (
                select recordid,
                  cast(fwildcardid as varchar(10)) fwildcardid,
                  cast(refnumber as varchar(10)) refnumber,
                  cast(wildcardname as varchar(10)) name,
                  cast(wildcardvalue as varchar(10)) value,
                  cast(comments as varchar(10)) comments,
                  row_number() over(partition by recordid
                                    order by fwildcardid) rn
                from tempp
              ) d
              unpivot
              (
                unpiv_value
                for col in (fwildcardid, refnumber, name, value, comments)
              ) c 
            ) src
            pivot 
            (
                max(unpiv_value)
                for col in (' + @cols + ')
            ) p '

execute(@query);

SQL Fiddle with Demo。这两个都给出了结果:

| RECORDID | FWILDCARDID1 | REFNUMBER1 | NAME1 | VALUE1 | COMMENTS1 | FWILDCARDID2 | REFNUMBER2 |  NAME2 | VALUE2 | COMMENTS2 |
-------------------------------------------------------------------------------------------------------------------------------
|   404450 |       154833 |          1 |    aa |     oi |         p |       154834 |          2 |    aaa |      p |         p |
|   406115 |       154867 |          1 |    98 |     ff |        ff |       (null) |     (null) | (null) | (null) |    (null) |
|   406199 |       154869 |          1 |   kki |   aaaa |      ssss |       (null) |     (null) | (null) | (null) |    (null) |
|   406212 |       154880 |          1 | bbbbb |   card |      comm |       (null) |     (null) | (null) | (null) |    (null) |

【讨论】:

  • 我也通过其他方式实现了这一点。但这种方法的问题是它对于不同的记录会有不同的 name1 值。我的要求是 aa 应该总是 name1 , 98 应该总是 name 2 , kki 应该总是 name 3 等等。如果记录没有通配符,名称为 aa 的那些 name1 应该为 null 类似地,其他字段为 1 也为 null,因为记录没有通配符 aa。
  • @KuntadyNithesh 请根据您的问题的完整要求编辑您的 OP。
  • 我更新了输出。看到那里 Name2 总是 "aa" 。如果没有名称为“aa”的记录,则所有后缀为 2 的列应为空
【解决方案2】:

无枢轴无交叉应用

根据已编辑问题。

select 
DISTINCT
A.recordId AS recordId,
A1.fwildcardId AS fwildcardId1,
A1.refNumber AS refNumber1,
A1.wildcardName AS wildcardName1,
A1.wildcardValue AS wildcardValue1,
A1.comments AS comments1,
A2.fwildcardId AS fwildcardId2,
A2.refNumber AS refNumber2,
A2.wildcardName AS wildcardName2,
A2.wildcardValue AS wildcardValue2,
A2.comments AS comments2,
A3.fwildcardId AS fwildcardId3,
A3.refNumber AS refNumber3,
A3.wildcardName AS wildcardName3,
A3.wildcardValue AS wildcardValue3,
A3.comments AS comments3,
A4.fwildcardId AS fwildcardId4,
A4.refNumber AS refNumber4,
A4.wildcardName AS wildcardName4,
A4.wildcardValue AS wildcardValue4,
A4.comments AS comments4,
A5.fwildcardId AS fwildcardId5,
A5.refNumber AS refNumber5,
A5.wildcardName AS wildcardName5,
A5.wildcardValue AS wildcardValue5,
A5.comments AS comments5,
A6.fwildcardId AS fwildcardId6,
A6.refNumber AS refNumber6,
A6.wildcardName AS wildcardName6,
A6.wildcardValue AS wildcardValue6,
A6.comments AS comments6,
A7.fwildcardId AS fwildcardId7,
A7.refNumber AS refNumber7,
A7.wildcardName AS wildcardName7,
A7.wildcardValue AS wildcardValue7,
A7.comments AS comments7,
A8.fwildcardId AS fwildcardId8,
A8.refNumber AS refNumber8,
A8.wildcardName AS wildcardName8,
A8.wildcardValue AS wildcardValue8,
A8.comments AS comments8,
A9.fwildcardId AS fwildcardId9,
A9.refNumber AS refNumber9,
A9.wildcardName AS wildcardName9,
A9.wildcardValue AS wildcardValue9,
A9.comments AS comments9,
A10.fwildcardId AS fwildcardId10,
A10.refNumber AS refNumber10,
A10.wildcardName AS wildcardName10,
A10.wildcardValue AS wildcardValue10,
A10.comments AS comments10
from Table_name A
LEFt JOIN Table_name A1 ON A.recordId=A1.recordId AND A1.wildcardName='aaa'
LEFT JOIN Table_name A2 ON A.recordId=A2.recordId AND A2.wildcardName='aa'
LEFT JOIN Table_name A3 ON A.recordId=A3.recordId AND A3.wildcardName='98'
LEFT JOIN Table_name A4 ON A.recordId=A4.recordId AND A4.wildcardName=''
LEFT JOIN Table_name A5 ON A.recordId=A5.recordId AND A5.wildcardName=''
LEFT JOIN Table_name A6 ON A.recordId=A6.recordId AND A6.wildcardName=''
LEFT JOIN Table_name A7 ON A.recordId=A7.recordId AND A7.wildcardName=''
LEFT JOIN Table_name A8 ON A.recordId=A8.recordId AND A8.wildcardName=''
LEFT JOIN Table_name A9 ON A.recordId=A9.recordId AND A9.wildcardName=''
LEFT JOIN Table_name A10 ON A.recordId=A10.recordId AND A10.wildcardName=''

SQL Fiddle

【讨论】:

  • 不,此查询也不会将通配符名称保持在固定位置
  • @KuntadyNithesh Gottcha。给我时间,我一定能给出答案。
  • 没问题。我会一直努力到巢穴!
  • 另外请提供4,5,6,7,8,9,10名称
  • 很难写所有东西。但我会说清楚的。说最大允许名称将是 10 。如果记录多于 1000 条,则它们的名称也将在这 10 个通配符名称中。一个记录 id 可以有多个通配符。对于所有记录,特定通配符名称应位于同一位置。一个特定的通配符名称不能重复记录。那就是记录 400000 不能有两次名为“aa”的通配符。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-20
相关资源
最近更新 更多