【问题标题】:How to convert Rows into Columns based on value如何根据值将行转换为列
【发布时间】:2019-01-21 20:58:42
【问题描述】:

我在一个表中有以下数据,在表中,每组在两行中包含两个 ON/OFF 值。我想根据状态将行转换为新列“Col1=>Col1_Status_ON/OFF”新名称

详情如下:

====================================================
| Group  | DateTime    | Status | Col1   |  Col2   |
====================================================
| Group1 | 01-Jan-2019 |  ON    | 101    |  102    |
| Group1 | 01-Jan-2019 |  OFF   | 201    |  202    |
| Group2 | 01-Jan-2019 |  ON    | 301    |  302    |
| Group2 | 01-Jan-2019 |  OFF   | 401    |  402    |
| Group3 | 01-Jan-2019 |  ON    | 501    |  502    |
| Group4 | 01-Jan-2019 |  OFF   | 601    |  602    |
====================================================

我想要返回如下的查询

    =======================================================================================
        | Group  | DateTime   |Col1_Satus_ON|Col1_Satus_OFF|Col2_Status_ON|Col2_Status_OFF|
    =======================================================================================
        | Group1 | 01-Jan-2019|   101       |   201        |    102       |   202         |
        | Group2 | 01-Jan-2019|   301       |   401        |    302       |   402         |
        | Group3 | 01-Jan-2019|   501       |   601        |    502       |   602         |        
    =======================================================================================

下面是生成表数据的SQL。

DROP TABLE IF EXISTS dbo.#MyTable;
SELECT CONVERT(VARCHAR(100),'')[Group], GETDATE()[DateTime],
       CONVERT(VARCHAR(100),'')[Status],(0)[Col1],(0)[Col2] 
       INTO #MyTable WHERE 1=2;

INSERT INTO #MyTable ([Group],[Datetime],[Status],[Col1],[Col2])
    SELECT 'Group1','01-Jan-2019 01:02:03','ON' ,101,102 UNION
    SELECT 'Group1','01-Jan-2019 01:02:03','OFF',201,202 UNION
    SELECT 'Group2','01-Jan-2019 01:02:03','ON' ,301,302 UNION
    SELECT 'Group2','01-Jan-2019 01:02:03','OFF',401,402 UNION
    SELECT 'Group3','01-Jan-2019 01:02:03','ON' ,501,502 UNION
    SELECT 'Group3','01-Jan-2019 01:02:03','OFF',601,602;

SELECT * FROM #MyTable;

请提出查询,

【问题讨论】:

  • 您好,您必须使用 group by 和 pivot
  • 如果可能,您应该考虑不使用保留字作为列名。这是允许的,但使用起来确实很痛苦。保留字通常很模糊,无论如何都不能成为很好的列名。
  • @pascalsanchez 你能写查询吗? ——
  • @Haseeb 查看答案中的查询。如果您有多个列,请查看动态查询或此帖子:stackoverflow.com/questions/10404348/…

标签: sql sql-server tsql pivot-table


【解决方案1】:

正如人们建议的那样,这是一个有效的动态支点

示例

Declare @UnPiv varchar(max),@SQL varchar(max)
Set @UnPiv = Stuff(( Select ','+quotename(name)
                      From  sys.dm_exec_describe_first_result_set(N'Select top 1 * from #MyTable',null,null )  A
                      Where Name not in ('Group','DateTime','Status')
                      For XML Path('')),1,1,'')

Set @SQL   = Stuff(( Select ','+quotename(name+Suffix)
                      From  sys.dm_exec_describe_first_result_set(N'Select top 1 * from #MyTable',null,null )  A
                      Cross Join ( values ('_Status_ON')
                                         ,('_Status_OFF')
                                 ) B(Suffix)
                       Where Name not in ('Group','DateTime','Status')
                       For XML Path('')),1,1,'')

Select @SQL = '
Select *
 From  (
        Select [Group]
              ,[DateTime]
              ,Item = concat(Item,''_Status_'',Status)
              ,Value
         From  (
                 Select * From #MyTable Unpivot (Value for Item in ('+@UnPiv+')) UnPiv
               ) A
       ) src
 Pivot (max(Value) for Item in ('+@SQL+') ) pvt
'
--Print @SQL
Exec(@SQL)

退货

【讨论】:

  • 完美!谢谢
【解决方案2】:

您可以使用条件聚合:

SELECT [Group], [Datetime],
    Col1_Status_ON  = MIN(IIF(Status='ON',  Col1, NULL)),
    Col1_Status_OFF = MIN(IIF(Status='OFF', Col1, NULL)),
    Col2_Status_ON  = MIN(IIF(Status='ON',  Col2, NULL)),
    Col2_Status_OFF = MIN(IIF(Status='OFF', Col2, NULL))
FROM #Mytable
GROUP BY [Group], [Datetime];

db<>fiddle demo

【讨论】:

  • thx 但上面的查询适合固定列,但是如果列不固定并且 col 的计数像 col1、col2、col3 到 colx 一样变化呢?
  • @Haseeb 这是查询。如果您有动态列数,则必须在动态 sql 查询中组合这些列。
  • @pascalsanchez 好的,我知道你是对的!!如果找不到最佳答案,我会标记您的答案。 :) 非常感谢
猜你喜欢
  • 1970-01-01
  • 2021-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-25
  • 1970-01-01
相关资源
最近更新 更多