33

UNPIVOTsは返されませんNULLが、比較で必要queryです。次の例の使用を避けようとしてISNULLいます(実際のSQLには100を超えるフィールドがあるため)。

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

代替案はありますか?

4

7 に答える 7

25

NULL を保持するには、CROSS JOIN ... CASE を使用します。

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 列のスクリプトを作成する必要がある場合があります。

于 2009-06-17T04:52:09.820 に答える
19

それは本当の痛みです。UNPIVOT操作するために生成された行がないため、の前にそれらを切り替える必要ISNULL()があります - コード生成はここであなたの友達です。

私も問題を抱えてPIVOTいます。欠落している行は に変わります。たとえば、欠落している値が同じである場合は、行全体NULLを折り返す必要があります。ISNULL()0.0

于 2009-06-16T19:57:53.953 に答える
3

または、SQLServer 2008 では短い方法で:

...
cross join 
(values('col1'), ('col2'), ('col3'), ('col4')) column_names(column_name)
于 2010-10-14T09:55:48.387 に答える
2

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 | 値|
+ ---------------------- + ----------------------- +
| 名前| blah1 |
| object_id | 3 |
| プリンシパルID| NULL | <======
| schema_id | 4 |
| parent_object_id | 0 |
| タイプ| 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 |
+ ---------------------- + ----------------------- +
    

于 2012-12-08T02:44:08.630 に答える
1

動的 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 )
于 2012-01-09T17:30:15.330 に答える
-1

ISNULL は答えの半分です。NULLIF を使用して NULL に変換します。例えば

DECLARE @temp TABLE(
    Foo varchar(50),
    Bar varchar(50) NULL
    );

INSERT INTO @temp( Foo,Bar )VALUES( 'licious',NULL );

SELECT * FROM @temp;

SELECT 
    Col,
    NULLIF( Val,'0Null' ) AS Val 
FROM(
    SELECT
        Foo,
        ISNULL( Bar,'0Null' ) AS Bar
    FROM
        @temp
    ) AS t
UNPIVOT(
    Val FOR Col IN(
        Foo,
        Bar 
        )
    ) up;

ここでは、中間値として「0Null」を使用します。好きなものを使用できます。ただし、「Null」のような現実世界のものを選択すると、ユーザー入力と衝突する危険があります。ガベージは "!@#34())0" で問題なく動作しますが、将来のコーダーにとってはさらに混乱する可能性があります。私はあなたが絵を手に入れると確信しています。

于 2014-10-10T17:22:58.797 に答える