【问题标题】:How to create a query on an existing table and build a table(view) with aggregated data and a restriction?如何在现有表上创建查询并使用聚合数据和限制构建表(视图)?
【发布时间】:2016-03-01 17:33:14
【问题描述】:

我拥有的是一个 MS-SQL 数据库,用于存储来自某些车辆上安装的设备的数据/信息(每辆车 1-3 个设备)。

目前,数据库中有一个名为 DeviceStatus 的表 - 一个大表,用于存储设备连接到 TCP 服务器时的所有信息。记录在此处添加(sql INSERT)或更新(sql UPDATE)。

表格如下所示:

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 设备的扩展;显然每辆车只有一个控制台) - 所以,这将是某种限制,以便在下面显示的所需表(视图)中获得正确的信息:)。

我需要的是一个 SQL 查询(命令/语句)来为所谓的“软件版本表”创建一个表(视图),我可以在其中查看安装在车辆中的所有设备的软件版本(所有这些)连接并与服务器通信)...类似于下表:

备注:414 的设备#1 丢失,因为它没有通信(我猜还没有……)

【问题讨论】:

  • 你只有3个SW版本还是无限数量的SW?我们可以复制/粘贴的样本比图片更好。您可以使用 SQLFiddle。为什么 414 没有位置 1 但我可以看到 device1SW 版本?
  • @JulienVavasseur:是的,每辆车最多 3 个:通常每个车门都安装一个设备。
  • 您应该包含 5-10 个 DeviceInfo 的样本和生成的 SwVersion,而不是 2 个随机屏幕截图。 Afaik,SwVersions 中显示的信息有一半以上未显示在DeviceInfo 表中。
  • 哦,nvm,我刚刚知道您的 DriverConsoleVersion 来自哪里,我以为您是按 Vehicule+Console 分组的。顺便说一句,朱利安错了;)
  • @groenhen 所以在DeviceInfo 中,任何给定的VehicleNo 都不会超过3 行?

标签: sql sql-server sql-server-2012 qsqlquery


【解决方案1】:

我喜欢 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,

【讨论】:

  • 我在 SQL Fiddle 中运行它(我现在在家),它可以工作。非常好,干净,简单:) 它为车辆 414 的 DriverConsoleVersion(在数据库中声明为 int 或 smallint)输出 0(零),可能最好在此处设置为 null,但我认为这并不重要。是的,我也会赞成这个答案。感谢 JB 分享这个:)
  • 文档说: CAST ( expression AS data_type [ ( length ) ] ) ,所以我猜 NUMERIC(8, 2) 意味着目标总长度为 8,其中 2 将用于小数...?我想小数点不计算在内......
  • 如果出于某种原因,有一个位置为 2 或 3 的驱动程序版本,将 DevicePosition = 1 时的大小写添加到 max() drivermonsoleversion 可能很有用
  • 即使没有order by VehicleNo(最后一行),它似乎也可以正常工作。 :)
  • @groenhen 没有 ORDER BY 也可以工作,但不保证您的订单是任何订单。
【解决方案2】:

根据我们目前掌握的信息,我认为您需要使用 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 表 LEFT JOIN 以获取与设备 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')
;

【讨论】:

  • 嗯,似乎不太好...有些设备有 SW 版本 8.01,它们不存在于他的输出中...也许“8.0x”会做这份工作?
  • 只是我的示例表中的一个数据类型问题。我将其更改为 varchar。首先是 int,四舍五入为 8。
  • 如果数据库将驱动程序控制台版本存储为整数(即​​ 134 -> 它实际上是...),是否有技巧将其在输出视图中“转换”为 1.34 至对用户来说更具可读性?另一方面,我看到的 DeviceSwVersion 是 varchar()。
  • 自 134 / 100 = 1.34 ?你可以使用: Cast(X as numeric(8,2))/100
猜你喜欢
  • 1970-01-01
  • 2015-09-09
  • 2022-01-12
  • 1970-01-01
  • 2018-04-22
  • 2016-03-25
  • 1970-01-01
  • 2017-09-18
  • 2014-12-28
相关资源
最近更新 更多