在尝试实现将Pivot
两行数据表变成一行的目标时,我的第一个想法是使用Cross Apply
. 通过使用Cross Apply
可以识别/生成具有从行的唯一 ID 派生的特定列名的每一行。(例如,“纬度”源列的“Lat1”和“Lat2”)。
INT
当我使用or数据类型时,一切都很好,FLOAT
但是当我尝试使用DateTime
all 时,一切都VALUES
变成了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');
成功交叉应用
如果我们使用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)
我们的结果符合预期:
伟大的!
与 DateTime 交叉应用失败
但是一旦我们添加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)
都变成DateTime
s
如果我的最终目标是将原始表中的所有值转换为一行,应该如何解决这个问题?
结果,值列必须像往常一样具有数据类型。SQL Server 使用数据类型优先级规则确定类型(更准确地说,
VALUES
子句是 aUNION
,所以类型在那里匹配)。在您的第一个示例中,优先规则给出了float类型的列。在第二个示例中,它是datetime。
通过将子句中的每个值
VALUES
显式转换为通用类型(例如varchar或sql_variant )来解决问题:或者:
注意:并非所有内容都可以转换为sql_variant。从那个链接:
除了旧的已弃用图像类型之外的所有内容都可以转换为char或varchar。请参阅数据类型转换(数据库引擎)中的转换矩阵: