添加日期时间时交叉应用失败

Ωme*_*Man 7 sql-server t-sql sql-server-2012 cross-apply

在尝试实现将Pivot两行数据表合并为一行的-ed 目标时,我的第一个想法是使用Cross Apply. 通过使用Cross Apply可以识别/生成具有从行的唯一 id 派生的特定列名的每一行。(例如,“纬度”源列的“纬度1”和“纬度2”)。

当我使用INTorFLOAT数据类型时一切都很好,但是当我尝试使用DateTimeall VALUESbecome 时DateTime


示例运输纬度/经度/日期时间

我们在两个不同的日子报道了船舶旅程中的两点:

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');
Run Code Online (Sandbox Code Playgroud)

成功的交叉应用 如果我们CrossApply对前三列的数据使用

  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)
Run Code Online (Sandbox Code Playgroud)

我们的结果符合预期:

使用 Int 和 Float 交叉应用成功

伟大的!


与日期时间交叉应用失败

但是一旦我们添加DateTime到组合中:

      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)
Run Code Online (Sandbox Code Playgroud)

都变成DateTimes

与 DateTime 交叉应用失败

如果我的最终目标是将原始表中的所有值转为一行,应该如何解决这个问题?

Pau*_*ite 14

在结果中,列必须有一个数据类型,就像往常一样。SQL Server 使用数据类型优先级规则确定类型(更准确地说,VALUES子句是 a UNION,因此类型在那里匹配)。

在您的第一个示例中,优先规则给出了一个类型为float的列。在第二个示例中,它是datetime

通过将VALUES子句中的每个值显式转换为公共类型(例如varcharsql_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);
Run Code Online (Sandbox Code Playgroud)

或者:

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);
Run Code Online (Sandbox Code Playgroud)

注意:并非所有内容都可以转换为sql_variant。从该链接:

限制

除了旧的不推荐使用的图像类型之外的所有内容都可以转换为charvarchar。参见数据类型转换(数据库引擎)中的转换矩阵:

转换矩阵