Frage

Unpivot wird keine Nulls zurückgeben, aber ich brauche sie in einer Vergleichsabfrage. Ich versuche, das folgende Beispiel zu vermeiden (da es in der realen SQL über 100 Felder gibt .:::

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

Irgendwelche Alternativen?

War es hilfreich?

Lösung

Es ist ein echter Schmerz. Sie müssen sie vor dem ausschalten UNPIVOT, weil es keine Reihe erstellt hat für ISNULL() Zu arbeiten - Codegenerierung ist Ihr Freund hier.

Ich habe das Problem auf PIVOT auch. Fehlende Reihen werden zu NULL, in was du einpacken musst ISNULL() ganz über die Zeile, wenn fehlende Werte die gleichen sind wie 0.0 zum Beispiel.

Andere Tipps

Verwenden Sie Cross Join ... Fall: Um Nulls zu erhalten, verwenden Sie: Fall: Fall:

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)

Anstatt von:

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

Ein Texteditor mit Spaltenmodus erleichtert solche Abfragen. Ultraedit hat es auch, auch Emacs. In EMACs heißt es rechteckige Bearbeitung.

Möglicherweise müssen Sie es für 100 Spalten einstellen.

Ich bin auf das gleiche Problem gestoßen. Verwendung CROSS APPLY (SQL Server 2005 und später) anstelle von Unpivot Problem gelöst. Ich fand die Lösung basierend auf diesem Artikel Eine alternative (bessere?) Methode zum Lösenund ich habe das folgende Beispiel gemacht, um zu demonstrieren, dass Cross -Anwendung Nulls wie nicht ignoriert 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

Oder in SQLServer 2008 auf kürzere Weise:

...
cross join 
(values('col1'), ('col2'), ('col3'), ('col4')) column_names(column_name)

Ich habe festgestellt, dass das linke äußere Ergebnis dem Unpivot -Ergebnis zu der vollständigen Liste der Felder, die bequem aus Information_Schema gezogen wurden, als praktische Antwort auf dieses Problem in einigen Kontexten sein.

-- 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>

Ausgabe sieht aus wie:

+----------------------+-----------------------+
|    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                     |
+----------------------+-----------------------+
    

Mit dynamischer SQL und Coalescecing habe ich das Problem wie dieses gelöst:

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 )

Isnull ist die halbe Antwort. Verwenden Sie NULLIF, um NULL zurückzusetzen. Z.B

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;

Hier verwende ich "0null" als meinen Zwischenwert. Sie können alles verwenden, was Sie mögen. Sie riskieren jedoch eine Kollision mit Benutzereingaben, wenn Sie etwas reales When wie "Null" auswählen. Müll funktioniert gut "!@#34 ()) 0", ist aber für zukünftige Codierer verwirrender. Ich bin sicher, Sie bekommen das Bild.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top