Cross Apply schlägt fehl, wenn DateTime hinzugefügt wird


7

Bei dem Versuch, ein PivotZiel für eine zweizeilige Datentabelle in einer Zeile zu erreichen, war mein erster Gedanke, a zu verwenden Cross Apply. Durch die Verwendung der Cross Applykann jede der Zeilen mit einem bestimmten Spaltennamen identifiziert / generiert werden, der von der eindeutigen ID der Zeile abgeleitet ist. (zB 'Lat1' und 'Lat2 für eine' Latitude'-Quellenspalte).

Alles ist in Ordnung, wenn ich INToder FLOATDatentypen verwende, aber wenn ich versuche, ein DateTimeAll zu verwenden, VALUESwerden DateTime.


Beispiel Versand Lat / Long / DateTime

Wir haben zwei Punkte in einer Schiffsreise, die an zwei verschiedenen Tagen gemeldet wurden:

CREATE TABLE #Shipping
(
     [RouteID]     [INT]  NOT NULL,
     [Latitude]    FLOAT NOT NULL, 
     [Longitude]   FLOAT NOT NULL,
     [Time]        DATETIME NOT NULL

);

INSERT #Shipping(RouteID, [Latitude], [Longitude], [Time])
VALUES          (1,         18.0221,    -63.1206,  '24-Jan-2016'), 
                (2,         17.8353,    -62.99667, '25-Jan-2016');

Erfolgreiches CrossApply Wenn wir CrossApplydie Daten für die ersten drei Spalten verwenden

  SELECT  col+cast([RouteID] as varchar(1)) new_col
         , X.value
       FROM #Shipping
  CROSS APPLY
  (
      VALUES
         (RouteID,   'Id')
      ,  (Latitude,  'Lat')
      ,  (Longitude, 'Lon')
  ) X (value, col)

Unsere Ergebnisse sind wie erwartet:

Cross Apply Erfolg mit Int und Float

Großartig!


Fehler CrossApply With DateTime

Aber sobald wir DateTimedie Mischung ergänzen :

      SELECT  col+cast([RouteID] as varchar(1)) new_col
             , X.value
           FROM #Shipping
      CROSS APPLY
      (
          VALUES
             (RouteID,   'Id')
          ,  (Latitude,  'Lat')
          ,  (Longitude, 'Lon')
          , ([Time],    'Time')
      ) X (value, col)

Alle werden DateTimes

Cross Apply-Fehler mit DateTime

Wie sollte man das umgehen, wenn mein Endziel darin besteht, alle Werte aus der ursprünglichen Tabelle in eine Zeile zu schwenken?

Antworten:


14

Im Ergebnis wird der Wert muss Spalte einen Datentyp haben, wie immer. SQL Server ermittelt den Typ anhand der Regeln für die Priorität des Datentyps (genauer gesagt, die VALUESKlausel ist a UNION, sodass die Typen dort übereinstimmen).

In Ihrem ersten Beispiel geben die Vorrangregeln eine Spalte vom Typ float an . Im zweiten Beispiel ist es Datum / Uhrzeit .

Lösen Sie das Problem, indem Sie jeden Wert in der VALUESKlausel explizit in einen gemeinsamen Typ umwandeln , z. B. varchar oder sql_variant :

SELECT
    new_col = X.col + CAST(S.RouteID as varchar(10)),
    X.value
FROM #Shipping AS S
CROSS APPLY
(
    VALUES
        (CONVERT(sql_variant, S.RouteID),   'Id'),
        (CONVERT(sql_variant, S.Latitude),  'Lat'),
        (CONVERT(sql_variant, S.Longitude), 'Lon'),
        (CONVERT(sql_variant, S.[Time]), 'Time')
) AS X (value, col);

oder:

SELECT
    new_col = X.col + CAST(S.RouteID as varchar(10)), 
    X.value
FROM #Shipping AS S
CROSS APPLY
(
    VALUES
        (CONVERT(varchar(8), S.RouteID),   'Id'),
        (CONVERT(varchar(8), S.Latitude),  'Lat'),
        (CONVERT(varchar(8), S.Longitude), 'Lon'),
        (CONVERT(varchar(8), S.[Time], 112), 'Time')
) AS X (value, col);

Hinweis: Nicht alles kann in sql_variant umgewandelt werden . Von diesem Link:

Beschränkungen

Alles außer dem alten veralteten Bildtyp kann in char oder varchar umgewandelt werden . Siehe die Konvertierungsmatrix unter Datentypkonvertierung (Datenbankmodul) :

Konvertierungsmatrix

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.