MySQL使用可变列名创建视图

时间:2013-11-03 16:24:44

标签: mysql sql

我使用1-Wire温度传感器和名为“LogTemp”的Windows应用程序记录温度值。

此应用程序自动将温度值存储在MySQL数据库中。

这是温度记录数据库:

mysql> show columns from logtemp; 
+------------------+----------+------+-----+---------------------+-------+ 
| Field | Type | Null | Key | Default | Extra | 
+------------------+----------+------+-----+---------------------+-------+ 
| DATETIME | datetime | NO | PRI | 0000-00-00 00:00:00 | | 
| 0400080224D59710 | float | YES | | NULL | | 
| CA00080224DDD010 | float | YES | | NULL | | 
| 5600080224E7FE10 | float | YES | | NULL | | 
| 0500080224D40B10 | float | YES | | NULL | | 
+------------------+----------+------+-----+---------------------+-------+ 

内容如下所示:

mysql> select * from logtemp limit 10; 
+---------------------+------------------+------------------+------------------+------------------+ 
| DATETIME | 0400080224D59710 | CA00080224DDD010 | 5600080224E7FE10 | 0500080224D40B10 | 
+---------------------+------------------+------------------+------------------+------------------+ 
| 2013-11-01 12:58:01 | 25.75 | 24.19 | 24.31 | 24.44 | 
| 2013-11-01 12:59:03 | 25.81 | 24.19 | 24.31 | 24.44 | 
| 2013-11-01 13:00:05 | 25.94 | 24.25 | 24.38 | 24.44 | 
| 2013-11-01 13:01:07 | 25.94 | 24.25 | 24.38 | 24.44 | 
| 2013-11-01 13:02:08 | 25.94 | 24.31 | 24.38 | 24.5 | 
| 2013-11-01 13:03:10 | 26.06 | 24.31 | 24.38 | 24.5 | 
| 2013-11-01 13:04:11 | 26.19 | 24.31 | 24.44 | 24.56 | 
| 2013-11-01 13:05:13 | 26.31 | 24.31 | 24.44 | 24.56 | 
| 2013-11-01 13:06:14 | 26.38 | 24.31 | 24.44 | 24.56 | 
| 2013-11-01 13:07:16 | 26.38 | 24.31 | 24.44 | 24.56 | 
+---------------------+------------------+------------------+------------------+------------------+ 

列名称(0400080224D59710等)是温度传感器的唯一ROM ID。当连接新传感器时,正在创建DB中的附加列 - 将传感器的ROM ID作为列名。

现在,我添加了另一个看起来像这样的表:

mysql> show columns from sensoren; 
+--------------------------+--------------+------+-----+---------+-------+ 
| Field | Type | Null | Key | Default | Extra | 
+--------------------------+--------------+------+-----+---------+-------+ 
| strSensorHex | varchar(16) | NO | PRI | NULL | | 
| strSensorBeschreibung | varchar(100) | NO | MUL | NULL | | 
| strSensorRRDTabellenName | varchar(25) | NO | | NULL | | 
+--------------------------+--------------+------+-----+---------+-------+ 

此表的内容为:

mysql> select * from sensoren; 
+------------------+-----------------------+--------------------------+ 
| strSensorHex | strSensorBeschreibung | strSensorRRDTabellenName | 
+------------------+-----------------------+--------------------------+ 
| 0400080224D59710 | Testsensor 1 | TEST1 | 
| CA00080224DDD010 | Testsensor 2 | TEST2 | 
| 5600080224E7FE10 | Testsensor 3 | TEST3 | 
| 0500080224D40B10 | Testsensor 4 | TEST4 | 
+------------------+-----------------------+--------------------------+ 

strSensorHex列包含温度传感器的唯一ROM ID。

现在我想创建一个包含以下信息的新视图:

DATETIME, strSensorHex, strSensorBeschreibung, Temperatur value

我已经尝试谷歌获取有关如何实现这一点的信息,但我还没有找到答案,我对SQL语法不是很熟悉:-(

2 个答案:

答案 0 :(得分:0)

评论有点长,但它包含两个解决此问题的想法。

虽然我同意BarMar的评论,但我认识到在现实世界中,事情可能不那么容易定义。

定义已知列表传感器的查询不是问题。类似的东西:

select DATETIME, s.strSensorHex, s.strSensorBeschreibung,
       (case when s.strSensorHex = '0400080224D59710' then lt.`0400080224D59710`
             . . .
        end) as Temperatur
from logtemp lt cross join
     sensoren s;

传感器列表在when语句中的一系列case语句中进行了硬编码。并且,幸运的是,您可以将其置于视图中,只需在其前面添加create view <blah> as语句即可。

问题是添加了一个新的传感器。视图不是动态的,不能动态地理解新的传感器值。 。 。但是,您可以使用预准备语句创建带有新case子句的SQL以合并逻辑。

我的第一个建议是您创建一个存储过程来处理添加新传感器的过程。此存储过程的一部分是使用预准备语句重新创建视图以重新定义视图。

可能有效的替代方案是采用审计表方法。向insert表添加logtemp触发器。此插入触发器会将行插入另一个表中,每个传感器只有一行。您可能还需要update触发器。

答案 1 :(得分:0)

一种可能的解决方案是使用动态SQL和存储过程而不是视图

DELIMITER $$
CREATE PROCEDURE sensortemp()
BEGIN
  SET @sql = NULL;

  SELECT GROUP_CONCAT(CONCAT(
           'WHEN s.strSensorHex = ''', strSensorHex, ''' THEN `', strSensorHex, '`')
         ORDER BY strSensorHex SEPARATOR ' ')
    INTO @sql
    FROM sensoren;

  SET @sql = CONCAT(
               'SELECT l.datetime, s.strSensorHex, s.strSensorBeschreibung, CASE ', @sql, 'END temperatur
                  FROM logtemp l CROSS JOIN sensoren s
                 ORDER BY l.datetime, s.strSensorBeschreibung'
             );

  PREPARE stmt FROM @sql;
  EXECUTE stmt;
  DEALLOCATE PREPARE stmt;
END$$
DELiMITER ;

样本用法:

CALL sensortemp();

示例输出:

|            DATETIME |     STRSENSORHEX | STRSENSORBESCHREIBUNG | TEMPERATUR |
|---------------------|------------------|-----------------------|------------|
| 2013-11-01 12:58:01 | 0400080224D59710 |          Testsensor 1 |      25.75 |
| 2013-11-01 12:58:01 | CA00080224DDD010 |          Testsensor 2 |      24.19 |
| 2013-11-01 12:58:01 | 5600080224E7FE10 |          Testsensor 3 |      24.31 |
| 2013-11-01 12:58:01 | 0500080224D40B10 |          Testsensor 4 |      24.44 |
| 2013-11-01 12:59:03 | 0400080224D59710 |          Testsensor 1 |      25.81 |
| 2013-11-01 12:59:03 | CA00080224DDD010 |          Testsensor 2 |      24.19 |
| 2013-11-01 12:59:03 | 5600080224E7FE10 |          Testsensor 3 |      24.31 |
| 2013-11-01 12:59:03 | 0500080224D40B10 |          Testsensor 4 |      24.44 |
| 2013-11-01 13:00:05 | 0400080224D59710 |          Testsensor 1 |      25.94 |
| 2013-11-01 13:00:05 | CA00080224DDD010 |          Testsensor 2 |      24.25 |
| 2013-11-01 13:00:05 | 5600080224E7FE10 |          Testsensor 3 |      24.38 |
| 2013-11-01 13:00:05 | 0500080224D40B10 |          Testsensor 4 |      24.44 |
...

这是 SQLFiddle 演示


更新:根据您的评论:您可以使用上面提到的代码来帮助您为视图构建定义(基本上是Gordon Linoff在他的回答中建议的)。您的视图定义可能类似于

CREATE VIEW vw_sensorentemp AS
  SELECT l.datetime, s.strSensorHex, s.strSensorBeschreibung, 
         CASE s.strSensorHex 
           WHEN '0400080224D59710' THEN `0400080224D59710` 
           WHEN '0500080224D40B10' THEN `0500080224D40B10` 
           WHEN '5600080224E7FE10' THEN `5600080224E7FE10` 
           WHEN 'CA00080224DDD010' THEN `CA00080224DDD010` 
         END temperatur 
  FROM logtemp l CROSS JOIN sensoren s;

现在您可以使用它以不同的方式对结果进行排序

SELECT * 
  FROM vw_sensorentemp
 ORDER BY strSensorBeschreibung DESC;

或加入其他表格。

注意:每次添加新内容或删除某些传感器时,您都必须更新视图的定义。

以下是该场景的 SQLFiddle 工作演示。