使用数据库结构中的计算列保存用户定义的视图

时间:2011-01-27 15:32:12

标签: database-design

我有来自db表中组织的各种传感器的采集数据。

我让用户能够创建自己的数据视图添加列,每个传感器一个,按数据分组,如下所示

 View #1
+---------------------+------+----+-----+
|      datetime       |  v1  | v2 |  v3 |
+---------------------+------+----+-----+
| 2010-09-13 00:05:00 | 40.9 |  1 | 0.3 |
| 2010-09-13 00:10:00 | 41.0 |  2 | 0.3 |
| 2010-09-13 00:15:00 | 41.1 |  4 | 0.3 |
+---------------------+------+----+-----+

要存储此类视图,我使用两个表:views和view_opts

views
    id
    name

view_opts
    id
    id_view
    id_sensor
    ord #for column ordering

现在我必须更进一步:添加更多列,不是直接来自传感器数据,而是计算其他列,如下所示:

 View #1
+---------------------+------+----+-----------+-----+
|      datetime       |  v1  | v2 | (v1+v2)/2 |  v3 |
+---------------------+------+----+-----------+-----+
| 2010-09-13 00:05:00 | 40.9 |  1 |   20.95   | 0.3 |
| 2010-09-13 00:10:00 | 41.0 |  2 |   21.5    | 0.3 |
| 2010-09-13 00:15:00 | 41.1 |  4 |   22.55   | 0.3 |
+---------------------+------+----+-----------+-----+

如果在SQL中不难实现这一点(我将旧的SELECT包装在一个新的SELECT中进行计算),我必须扩展我存储Views的方式。

我想过几个方面,都有一些专业和很多缺点......

有什么好主意吗?

=====

编辑:

我的一个想法是向view-opts添加一个文本字段,让用户以类似SQL的语法添加自己的计算:

(v1+v2)/2

如果view_opt中的传感器外键为空,则在查询中使用该文本,如:

SELECT v1, v2, (v1+v2)/2, v3 FROM (
    SELECT v1, v2, v3 FROM ...
)

当然我应该解析(v1+v2)/2部分的语法错误,注入(不太可能,此功能仅适用于对破坏自己的数据没有兴趣的可信管理用户)。

===============

添加:

这里是我数据库中关键表的som DDL(我修剪了这个问题不需要的一些字段和表格):

CREATE TABLE acquisitions (
    id INTEGER NOT NULL, 
    id_cu INTEGER NOT NULL, 
    datetime DATETIME NOT NULL, 
    PRIMARY KEY (id), 
    FOREIGN KEY(id_cu) REFERENCES ctrl_units (id), 
)

CREATE TABLE data (
    id INTEGER NOT NULL, 
    id_acq INTEGER NOT NULL, 
    id_meas INTEGER NOT NULL, 
    value FLOAT, 
    PRIMARY KEY (id), 
    FOREIGN KEY(id_acq) REFERENCES acquisitions (id)
)

CREATE TABLE sensors (
    id_cu INTEGER NOT NULL, 
    id_meas INTEGER NOT NULL, 
    name VARCHAR(40) NOT NULL, 
    PRIMARY KEY (id_cu, id_meas), 
    FOREIGN KEY(id_cu) REFERENCES ctrl_units (id)
)

CREATE TABLE ctrl_units (
id INTEGER NOT NULL, 
name VARCHAR(40) NOT NULL, 
PRIMARY KEY (id)
)

简要说明:我有ctrl_units通过网络在csv文件中发送数据,每个ctrl_unit有多个sensors,一个sensor }被标识为id_cu-id_meas

这是我找到的解决方案,但真实的方式ctrl_units通过网络发送数据。

每次采集都是csv中的一行,日期时间和许多传感器测量值为id_meas, value简化版:说明所有传感器都会在采集中发送更多测量值{{1根据传感器类型,id_meas, id_elab, value具有不同的含义)

以这种方式工作传感器(结果列)的数据由其控制单元ID(存储在父获取中)识别,并且它是测量类型ID(存储在单个数据中)。 我使用this query来提取数据。

2 个答案:

答案 0 :(得分:1)

为了能够保留查询中的顺序,并允许计算列出现在正确的位置,你真的需要在view_opts表中作为占位符。怎么样:

view_opts
id
id_view
isCalc bit --contains 0 for Sensor and 1 for Calc (not strictly necessary)
id_sensor --nullable
id_viewcalc --nullable
ord #for column ordering

可以为空的列应该意味着可以保持fk关系。

然后是一个额外的计算表(以避免垃圾邮件发送到view_opts表):

view_calcs
id_viewcalc
...

然后您可以选择使用一组预定义的计算可用,并引用这些计算以及所需的列,或者允许一组完全可配置的计算(我建议第一个,因为第二个可以最终得到一个计算结果)可怕的UI)。

答案 1 :(得分:1)

如果用户可以创建视图,为什么不简单地GRANT CREATE VIEW TO user_role。他们可以自己编写计算。然后他们将拥有SQL Views的全部功能。你或我能提出的任何事情都将是:

  • 其中的一小部分,

  • 需要额外的表格和维护

实施

鉴于你必须实施它,那么。

最好的方法仍然是在您的应用程序代码中尽可能少地执行,并尽可能在SQL和SQL工具中执行。解析输入请求并构建查询很困难,并且您不希望每次提出新请求时都要更改它。

你所拥有的是相当硬编码和脆弱的;它们似乎是汇总表,只做一件事。相反,在数据库中构建向量。在Dimension-Fact结构中,这是数据仓库中的常见做法,而不是摘要表。如果您发布一些DDL(3或4个关键表用作源,对于您问题中的“视图”),我可以提供更具体的指示。

当然,如果您的数据库不是数据库,那么将阻止数据库和SQL可以预期的基本功能。有一半的时间,这些备案系统只需要重新实施,努力从非数据库提供普通功能并维护它们的成本远远超过重新实施成本。

另一半时间,可以通过实现一些SQL视图来克服残缺的非数据库,每个SQL视图都提供了规范化表的功能。但是,在做出是否可能的决定之前,需要仔细分析,这在SO上是不可能的。然后,您可以像在真实数据库中的上一样在视图上构建矢量或维度。

每个Vector或Dimension都是一个Scalar子查询,用于填充单个列。外部查询定义结果集(网格)的结构。子查询填充单元格。

最后,在您的应用程序中,现在可以是一个更简单的解析器,给定输入数据,它可以获取一个或两个向量,或另一个向量除以的向量,等等。构建SELECT语句,然后执行EXECUTE。