如何在现有 table 上创建查询并构建具有聚合数据和限制的 table(view)?
How to create a query on an existing table and build a table(view) with aggregated data and a restriction?
我有一个 MS-SQL 数据库,用于存储 data/info 来自安装在某些车辆上的设备(每辆车 1-3 个设备)。
目前,在名为 DeviceStatus 的数据库中有一个 table - 一个很大的 table 用于存储设备连接到 TCP 服务器时的所有信息。在此处添加(sql INSERT)或更新(sql UPDATE)记录。
table 看起来像这样:
Sample data:
1040 305 3 8.00 0
1044 305 2 8.00 0
1063 305 1 8.01 1.34
1071 312 2 8.00 0
1075 312 1 8.00 1.33
1078 312 3 8.00 0
1099 414 3 8.00 0
1106 414 2 8.01 0
1113 102 1 8.01 1.34
1126 102 3 8.00 0
备注: 驱动控制台总是与安装在第一个位置的设备相关(它是位置1上的设备的扩展;显然只有一个控制台每辆车) - 因此,这将是某种 限制 ,以便在下面显示的所需 table(视图)中获得正确的信息 :) .
我需要的是一个 SQL 查询 (command/statement) 来为所谓的 "Software Versions Table" 创建一个 table(视图),我可以在其中看到安装在车辆上的所有设备的软件版本(所有与服务器连接和通信的设备)...类似于下面的 table:
备注:414 的设备#1 丢失,因为它没有通信(我猜还没有……)
根据我们目前掌握的信息,我认为您需要使用 PIVOT 进行查询:
SELECT P.VehicleNo, V.DriverConsoleVersion, P.[1] AS [Device1SwVersion], P.[2] AS [Device1SwVersion], P.[3] AS [Device1SwVersion]
FROM (
SELECT VehicleNo, [1], [2], [3]
FROM (
SELECT VehicleNo, DevicePosition, DeviceSwVersion
FROM @DeviceInfo
) as d
PIVOT (
MAX(DeviceSwVersion)
FOR DevicePosition IN ([1], [2], [3])
) PIV
) P
LEFT JOIN @DeviceInfo V
ON V.VehicleNo = P.VehicleNo AND V.DevicePosition = 1;
您可以使用此类查询创建视图。
第一个子查询为每辆车的设备 1 到 3 获取 4 列。
然后它与 SwVersion table 左加入,以获得与设备 1 关联的控制台版本。
输出:
VehicleNo DriverConsoleVersion Device1SwVersion Device1SwVersion Device1SwVersion
102 1.34 8.01 NULL 8.00
305 1.34 8.01 8.00 8.00
312 1.33 8.00 8.00 8.00
414 NULL NULL 8.01 8.00
您的数据:
Declare @DeviceInfo TABLE([DeviceSerial] int, [VehicleNo] int, [DevicePosition] int, [DeviceSwVersion] varchar(10), [DriverConsoleVersion] varchar(10));
INSERT INTO @DeviceInfo([DeviceSerial], [VehicleNo], [DevicePosition], [DeviceSwVersion], [DriverConsoleVersion])
VALUES
(1040, 305, 3, '8.00', '0'),
(1044, 305, 2, '8.00', '0'),
(1063, 305, 1, '8.01', '1.34'),
(1071, 312, 2, '8.00', '0'),
(1075, 312, 1, '8.00', '1.33'),
(1078, 312, 3, '8.00', '0'),
(1099, 414, 3, '8.00', '0'),
(1106, 414, 2, '8.01', '0'),
(1113, 102, 1, '8.01', '1.34'),
(1126, 102, 3, '8.00', '0')
;
我喜欢 PIVOT 答案,但这是另一种方式:
select VehicleNo,
max(DriverConsoleVersion) DriverConsoleVersion,
max(case when DevicePosition = 1 then DeviceSwVersion end) Device1SwVersion,
max(case when DevicePosition = 2 then DeviceSwVersion end) Device2SwVersion,
max(case when DevicePosition = 3 then DeviceSwVersion end) Device3SwVersion
from @DeviceInfo
group by VehicleNo
order by VehicleNo
您还可以对它们进行转换或格式化。所以一个可能是:
select ...,
isnull(cast(cast(
max(case when DevicePosition = 1 then DeviceSwVersion end)
as decimal(8,2)) / 100) as varchar(5)), '') Device1SwVersion,
我有一个 MS-SQL 数据库,用于存储 data/info 来自安装在某些车辆上的设备(每辆车 1-3 个设备)。
目前,在名为 DeviceStatus 的数据库中有一个 table - 一个很大的 table 用于存储设备连接到 TCP 服务器时的所有信息。在此处添加(sql INSERT)或更新(sql UPDATE)记录。
table 看起来像这样:
Sample data:
1040 305 3 8.00 0
1044 305 2 8.00 0
1063 305 1 8.01 1.34
1071 312 2 8.00 0
1075 312 1 8.00 1.33
1078 312 3 8.00 0
1099 414 3 8.00 0
1106 414 2 8.01 0
1113 102 1 8.01 1.34
1126 102 3 8.00 0
备注: 驱动控制台总是与安装在第一个位置的设备相关(它是位置1上的设备的扩展;显然只有一个控制台每辆车) - 因此,这将是某种 限制 ,以便在下面显示的所需 table(视图)中获得正确的信息 :) .
我需要的是一个 SQL 查询 (command/statement) 来为所谓的 "Software Versions Table" 创建一个 table(视图),我可以在其中看到安装在车辆上的所有设备的软件版本(所有与服务器连接和通信的设备)...类似于下面的 table:
备注:414 的设备#1 丢失,因为它没有通信(我猜还没有……)
根据我们目前掌握的信息,我认为您需要使用 PIVOT 进行查询:
SELECT P.VehicleNo, V.DriverConsoleVersion, P.[1] AS [Device1SwVersion], P.[2] AS [Device1SwVersion], P.[3] AS [Device1SwVersion]
FROM (
SELECT VehicleNo, [1], [2], [3]
FROM (
SELECT VehicleNo, DevicePosition, DeviceSwVersion
FROM @DeviceInfo
) as d
PIVOT (
MAX(DeviceSwVersion)
FOR DevicePosition IN ([1], [2], [3])
) PIV
) P
LEFT JOIN @DeviceInfo V
ON V.VehicleNo = P.VehicleNo AND V.DevicePosition = 1;
您可以使用此类查询创建视图。
第一个子查询为每辆车的设备 1 到 3 获取 4 列。 然后它与 SwVersion table 左加入,以获得与设备 1 关联的控制台版本。
输出:
VehicleNo DriverConsoleVersion Device1SwVersion Device1SwVersion Device1SwVersion
102 1.34 8.01 NULL 8.00
305 1.34 8.01 8.00 8.00
312 1.33 8.00 8.00 8.00
414 NULL NULL 8.01 8.00
您的数据:
Declare @DeviceInfo TABLE([DeviceSerial] int, [VehicleNo] int, [DevicePosition] int, [DeviceSwVersion] varchar(10), [DriverConsoleVersion] varchar(10));
INSERT INTO @DeviceInfo([DeviceSerial], [VehicleNo], [DevicePosition], [DeviceSwVersion], [DriverConsoleVersion])
VALUES
(1040, 305, 3, '8.00', '0'),
(1044, 305, 2, '8.00', '0'),
(1063, 305, 1, '8.01', '1.34'),
(1071, 312, 2, '8.00', '0'),
(1075, 312, 1, '8.00', '1.33'),
(1078, 312, 3, '8.00', '0'),
(1099, 414, 3, '8.00', '0'),
(1106, 414, 2, '8.01', '0'),
(1113, 102, 1, '8.01', '1.34'),
(1126, 102, 3, '8.00', '0')
;
我喜欢 PIVOT 答案,但这是另一种方式:
select VehicleNo,
max(DriverConsoleVersion) DriverConsoleVersion,
max(case when DevicePosition = 1 then DeviceSwVersion end) Device1SwVersion,
max(case when DevicePosition = 2 then DeviceSwVersion end) Device2SwVersion,
max(case when DevicePosition = 3 then DeviceSwVersion end) Device3SwVersion
from @DeviceInfo
group by VehicleNo
order by VehicleNo
您还可以对它们进行转换或格式化。所以一个可能是:
select ...,
isnull(cast(cast(
max(case when DevicePosition = 1 then DeviceSwVersion end)
as decimal(8,2)) / 100) as varchar(5)), '') Device1SwVersion,