0

我有一个 MySQL 数据库,我正在保存来自几个不同传感器的温度读数。我最初考虑使用三个不同的表来存储我的数据:

mysql> select * from sensor_info;
+----+------------------+------+--------+
| id | address          | name | active |
+----+------------------+------+--------+
|  1 | 28D684CD02000057 | NULL |      1 |
|  2 | 28099B49030000D8 | NULL |      1 |
|  3 | 28339ACD0200004B | NULL |      1 |
+----+------------------+------+--------+

mysql> select * from data_period limit 4;
+----+---------------------+
| id | ts                  |
+----+---------------------+
|  1 | 2012-06-30 09:35:02 |
|  2 | 2012-06-30 09:36:22 |
|  3 | 2012-06-30 09:37:46 |
|  4 | 2012-06-30 09:40:36 |
+----+---------------------+

mysql> select * from data_points limit 4;
+----+-------------+-----------+-------+
| id | data_period | sensor_id | data  |
+----+-------------+-----------+-------+
|  1 |           1 |         1 | 77.90 |
|  2 |           1 |         2 | 77.34 |
|  3 |           1 |         3 | 77.56 |
|  4 |           2 |         1 | 78.01 |
+----+-------------+-----------+-------+

我正在尝试做的是获取我存储的数据并将其放入 CSV 文件中,以便我可以使用dygraphs Javascript library显示它。我需要把我的数据变成这样的格式:

date,temp1,temp2,temp3
2012-06-30 09:35:02,77.90,77.34,77.56
2012-06-30 09:36:22,78.01,77.36,77.59
....

我开始执行此操作的每一种方式(使用 PHP),我似乎都让这变得过于复杂,并且必须将查询放在循环内的循环内。我是否让自己变得比我需要的更难?

大部分工作是使用查询还是使用 PHP 完成?以后,如果特定时间戳中缺少温度读数,我还想添加将 NULL 放入 CSV 的代码。

我不是在寻找一个非常具体的答案,我只是想知道我应该往哪个方向走。我什至不知道如何开始格式化数据库中的数据,或者我是否应该尝试使用不同的格式将我的信息存储在数据库中。

4

3 回答 3

2

我会运行一个单一的选择查询来将很多东西连接在一起。您可以在可能没有数据的地方使用外连接。

SELECT data_period.ts AS date, dp1.data AS temp1, dp2.data AS temp2, dp3.data AS temp3
FROM data_period
LEFT OUTER JOIN data_points AS dp1 ON dp1.data_period=data_period.id AND dp1.sensor_id=1
LEFT OUTER JOIN data_points AS dp2 ON dp2.data_period=data_period.id AND dp2.sensor_id=2
LEFT OUTER JOIN data_points AS dp3 ON dp3.data_period=data_period.id AND dp3.sensor_id=3

(参见:SQL Fiddle 示例

这应该为您提供一组结果,您可以循环访问这些结果。

如果您真的希望 MySQL 完成大部分工作,您可以将第一行更改为(我认为) SELECT data_period.ts +','+ IFNULL(dp1.data,'NULL') +','+ IFNULL(dp2 .data,'NULL') +','+ IFNULL(dp3.data,'NULL')

综合评论和答案并将其保存到文件中:

SELECT data_period.ts AS date, dp1.data AS temp1, dp2.data AS temp2, dp3.data AS temp3
INTO OUTFILE '/home/user/output.csv'
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '"'
ESCAPED BY '\\'
LINES TERMINATED BY '\n'
FROM data_period LEFT OUTER JOIN data_points AS dp1 ON dp1.data_period=data_period.id      
AND dp1.sensor_id=1 LEFT OUTER JOIN data_points AS dp2 ON  
dp2.data_period=data_period.id   AND dp2.sensor_id=2 LEFT OUTER JOIN data_points AS dp3 
ON dp3.data_period=data_period.id AND dp3.sensor_id=3;
于 2012-06-30T23:13:48.237 回答
0

为此,您可以使用两个 SQL 语句,给出一个外循环和一个内循环。第一个声明

select  ts from data_points as point 
inner join data_period on data_period = data_period.id 
group by ts 
order by ts

将获得您有数据的日期列表。

内部循环中的第二个将获得按传感器 ID 排序的数据值列表 - 如果您在 data_points 中有缺失值,那么该列表将是错误的并且有间隙;因此,如果您确实有差距,您可能需要执行额外的步骤来获取传感器列表,然后从查询返回的数据中填充此列表。

以下示例说明了如何继续此操作。

// get the outer list
$sql = "select  ts from data_points as point 
        inner join data_period on data_period=data_period.id 
        group by ts 
        order by ts";

$result = mysql_query($sql);

$result || die(mysql_error());

while($row = mysql_fetch_row($result))
{
    // get the date for the second query
    $date = $row[0];

    $sql = "select  data from data_points as point
            inner join data_period on data_period=data_period.id
            inner join sensor_info on sensor_id = sensor_info .id
            where ts = '$date'
            order by sensor_id";

    $result_1 = mysql_query($sql);

    // now create an array from the values - we could use mysql_fetch_array to do this
    // but this way allows us the possibility of extending the processing to 
    // take into account missing values.
    $vals = array();
    while($row_1 = mysql_fetch_row($result_1)) {
        $vals[]=$row_1[0];
    }
    print "$date,".join(",",$vals)."\n";
}
于 2012-06-30T23:43:28.177 回答
0

我建议事后只在 php 中进行 csv 格式设置。

这是我在网上找到并且非常喜欢使用的一个方便的功能。如果您将 SQL 调用包装在一个类中,那么您可以在查询后使用此方法。:)

注意我将它修改为我的 MSSQL,但很容易用 mysql 替换它。

  public final function SQL2CSV() {
        // set initial .csv file contents
        $CSV = array();
        $rowid = 0;
        //This would be your query.
        $res = $this->fetchQuery();

        // get column captions and enclose them in doublequotes (") if $print_captions is not set to false
            for ($i = 0; $i < mssql_num_fields($res); $i++) {
                $fld = mssql_fetch_field($res, $i);
                $colnames[] = $fld->name;
            }
            // insert column captions at the beginning of .csv file
            $CSV[$rowid] = implode(",", $colnames);


        // iterate through each row
        // replace single double-quotes with double double-quotes
        // and add values to .csv file contents
        if (mssql_num_rows($res) > 0) {
            while ($row = mssql_fetch_array($res, MSSQL_NUM)) {
                $rowid++;
                for ($i = 0; $i < sizeof($row); $i++)
                    //$row[$i] = '"'.str_replace('"', '""', $row[$i]).'"';
                    $row = str_replace (',', '', $row);

                $CSV[$rowid] = "\n".implode(",", $row);

            }
        }


        RETURN $CSV;
    }
于 2012-06-30T23:45:18.850 回答