代码之家  ›  专栏  ›  技术社区  ›  JeffO

SQL Server-使用UNPIVOT包含NULL

  •  35
  • JeffO  · 技术社区  · 16 年前

    UNPIVOT NULL query ISNULL

    Select ID, theValue, column_name
    From 
    (select ID,
      ISNULL(CAST([TheColumnToCompare]  AS VarChar(1000)), '') as TheColumnToCompare
      from MyView
      where The_Date = '04/30/2009'
    ) MA
    UNPIVOT
       (theValue FOR column_name IN 
       ([TheColumnToCompare])
    ) AS unpvt
    

    有其他选择吗?

    9 回复  |  直到 5 年前
        1
  •  24
  •   Michel de Ruiter    6 年前

    要保留NULL,请使用CROSS JOIN。..案例:

    select a.ID, b.column_name
    , column_value = 
        case b.column_name
          when 'col1' then a.col1
          when 'col2' then a.col2
          when 'col3' then a.col3
          when 'col4' then a.col4
        end
    from (
      select ID, col1, col2, col3, col4 
      from table1
      ) a
    cross join (
      select 'col1' union all
      select 'col2' union all
      select 'col3' union all
      select 'col4'
      ) b (column_name)
    

    而不是:

    select ID, column_name, column_value
    From (
      select ID, col1, col2, col3, col4
      from table1
      ) a
    unpivot (
      column_value FOR column_name IN (
        col1, col2, col3, col4)
      ) b
    

    具有列模式的文本编辑器使此类查询更容易编写。UltraEdit有,Emacs也有。在Emacs中,它被称为矩形编辑。

    您可能需要为100列编写脚本。

        2
  •  19
  •   Cade Roux    16 年前

    UNPIVOT ISNULL()

    我有问题 PIVOT 也。缺失的行变成 NULL ,你必须把它包起来 ISNULL() 0.0

        3
  •  9
  •   Tom Blodget    6 年前

    我也遇到了同样的问题。使用 CROSS APPLY (SQL Server 2005及更高版本)而不是 Unpivot 解决了问题。我根据这篇文章找到了解决方案 An Alternative (Better?) Method to UNPIVOT 逆透视 .

    create table #Orders (OrderDate datetime, product nvarchar(100), ItemsCount float, GrossAmount float, employee nvarchar(100))
    
     insert into #Orders
     select getutcdate(),'Windows',10,10.32,'Me'
     union 
     select getutcdate(),'Office',31,21.23,'you'
     union 
     select getutcdate(),'Office',31,55.45,'me'
     union  
     select getutcdate(),'Windows',10,null,'You'
    
    SELECT OrderDate, product,employee,Measure,MeasureType
     from #Orders orders
     CROSS APPLY (
        VALUES ('ItemsCount',ItemsCount),('GrossAmount',GrossAmount)
        ) 
        x(MeasureType, Measure) 
    
    
    SELECT OrderDate, product,employee,Measure,MeasureType
    from #Orders orders
    UNPIVOT
       (Measure FOR MeasureType IN 
          (ItemsCount,GrossAmount)
    )AS unpvt;
    
    
     drop table #Orders
    
        4
  •  3
  •   chue x    11 年前

    或者,在SQLServer 2008中,以更短的方式:

    ...
    cross join 
    (values('col1'), ('col2'), ('col3'), ('col4')) column_names(column_name)
    
        5
  •  2
  •   Beej    13 年前

    使用动态SQL和COALESCE,我解决了这样的问题:

    DECLARE @SQL NVARCHAR(MAX)
    DECLARE @cols NVARCHAR(MAX)
    DECLARE @dataCols NVARCHAR(MAX)
    
    SELECT 
        @dataCols = COALESCE(@dataCols + ', ' + 'ISNULL(' + Name + ',0) ' + Name , 'ISNULL(' + Name + ',0) ' + Name )
    FROM Metric WITH (NOLOCK)
    ORDER BY ID
    
    SELECT 
        @cols = COALESCE(@cols + ', ' + Name , Name )
    FROM Metric WITH (NOLOCK)
    ORDER BY ID
    
    SET @SQL = 'SELECT ArchiveID, MetricDate, BoxID, GroupID, ID MetricID, MetricName, Value
                FROM 
                   (SELECT ArchiveID, [Date] MetricDate, BoxID, GroupID,  ' + @dataCols + '
                    FROM MetricData WITH (NOLOCK)
                    INNER JOIN Archive WITH (NOLOCK)
                        ON ArchiveID = ID
                    WHERE BoxID = ' + CONVERT(VARCHAR(40), @BoxID) + '
                    AND GroupID = ' + CONVERT(VARCHAR(40), @GroupID) + ') p
                UNPIVOT
                   (Value FOR MetricName IN 
                      (' + @cols + ')
                )AS unpvt
                INNER JOIN Metric WITH (NOLOCK)
                    ON MetricName  = Name
                ORDER BY MetricID, MetricDate'
    
    EXECUTE( @SQL )
    
        6
  •  1
  •   Charlie    14 年前

    我发现,在某些情况下,将UNPIVOT结果连接到完整字段列表的左外连接(方便地从INFORMATION_SCHEMA中提取)是解决这个问题的实用答案。

    -- test data
    CREATE TABLE _t1(name varchar(20),object_id varchar(20),principal_id varchar(20),schema_id varchar(20),parent_object_id varchar(20),type varchar(20),type_desc varchar(20),create_date varchar(20),modify_date varchar(20),is_ms_shipped varchar(20),is_published varchar(20),is_schema_published varchar(20))
    INSERT INTO _t1 SELECT 'blah1', 3, NULL, 4, 0, 'blah2', 'blah3', '20100402 16:59:23.267', NULL, 1, 0, 0 
    
    -- example
    select c.COLUMN_NAME, Value
    from INFORMATION_SCHEMA.COLUMNS c
    left join (
      select * from _t1
    ) q1
    unpivot (Value for COLUMN_NAME in (name,object_id,principal_id,schema_id,parent_object_id,type,type_desc,create_date,modify_date,is_ms_shipped,is_published,is_schema_published)
    ) t on t.COLUMN_NAME = c.COLUMN_NAME
    where c.TABLE_NAME = '_t1'
    </pre>
    

    输出如下:

    +----------------------+-----------------------+
    |    COLUMN_NAME       |        Value          |
    +----------------------+-----------------------+
    | name                 | blah1                 |
    | object_id            | 3                     |
    | principal_id         | NULL                  | <======
    | schema_id            | 4                     |
    | parent_object_id     | 0                     |
    | type                 | blah2                 |
    | type_desc            | blah3                 |
    | create_date          | 20100402 16:59:23.26  |
    | modify_date          | NULL                  | <======
    | is_ms_shipped        | 1                     |
    | is_published         | 0                     |
    | is_schema_published  | 0                     |
    +----------------------+-----------------------+
        
        7
  •  -1
  •   John Kelly    11 年前

    我也有你的问题,这是 我的快速而肮脏的解决方案:

     select 
         Month,Name,value 
         from TableName 
     unpivot     
      (        
       Value  for Name in (Col_1,Col_2,Col_3,Col_4,Col_5
      )
    ) u  
        
    

    替换为:

    select Month,Name,value from 
        ( select 
              isnull(Month,'no-data') as Month,
              isnull(Name,'no-data') as Name,
              isnull(value,'no-data') as value from TableName
        ) as T1
    unpivot
    (
        Value 
        for Name in (Col_1,Col_2,Col_3,Col_4,Col_5)  
    ) u 
    

    好的,空值将被替换为字符串,但所有行都将返回!!