1

我的桌子:

hourly_weather                 electrical_readings
----------------               -----------------------
meter | time_read | temp       meter | time      | kwh
----------------               -----------------------
1       1316044800  55         1       1316136250  19.24
1       1316138400  56         1       1316044320  18.29
(...)                          (...)

我想从这些数据中检索两个重要的值:

1)我想要给定一天的总KW

2)我想要那天的最高温度

我正在使用的查询需要 WAYYYY 太长时间才能运行,但我想不出另一种方法来做到这一点。就像,两个表中的 100,000 行数据需要几个小时。

SELECT * FROM (
SELECT * , SUM(kwh) AS sumkwh, 
           DATE( FROM_UNIXTIME( r.time_read ) ) AS datex, 
           UNIX_TIMESTAMP( DATE( FROM_UNIXTIME( r.time_read ) ) ) AS datey, 
           (
               SELECT MAX( temp )
               FROM hourly_weather hw
               WHERE hw.meter = 1
                 AND time_read >= datey
                 AND time_read < datey + 86400
           ) AS temp
FROM electrical_readings r
WHERE id = 1
GROUP BY datex
) as t1
WHERE t1.temp != '';
4

2 回答 2

2

我认为在单独的查询中计算这两个值然后加入结果数据集会更简单。您甚至可以定义临时变量和表以使事情变得更容易:

# Temp variables for the dates
set @t0 = cast('2013-02-01' as date);
set @t1 = cast('2013-02-02' as date);

# Temporary table 1: Sum of KWH
create temporary table temp_sum_kw
    select 
        date(from_unixtime(timeread)) as `date`, sum(KWH) as sum_kwh
    from 
        electrical_readings
    where 
        timeread >= unix_timestamp(@t0) and timeread < unix_timestamp(date_add(@t1, interval +1 day))
    group by 
        date(from_unixtime(timeread));
alter table temp_sum_kw
    add index idx_date(`date`);

# Temporary table 2: Max temp
create temporary table temp_max_temperature
    select 
        date(from_unixtime(timeread)) as `date`, max(temp) as max_temp
    from 
        hourly_weather
    where 
        (timeread >= @t0 and timeread < date_add(@t1, interval +1 day))
        and meter = 1
    group by 
        date(from_unixtime(timeread));
alter table temp_max_temperature
    add index idx_date(`date`);

# Put it all together
select 
    m.*, t.max_temp
from
    temp_sum_kw as m
    inner join temp_max_temperature as t on m.`date` = t.`date`;

where使用条件的原因timeread >= @t0 and timeread < date_add(@t1, interval +1 day)是包括直到最后一刻发生的所有事情@t1

希望这可以帮助你

于 2013-04-15T17:07:58.167 回答
2
SELECT DATE(FROM_UNIXTIME(r.time_read)) AS datex, 
  SUM(r.kwh) AS sumkwh, MAX(hw.temp) AS temp
FROM electrical_readings r
LEFT OUTER JOIN hourly_weather hw
  ON DATE(FROM_UNIXTIME(r.time_read)) = DATE(FROM_UNIXTIME(hw.time_read)) 
  AND hw.meter = 1
WHERE r.id = 1
GROUP BY datex
HAVING temp IS NOT NULL

这仍然是性能问题,因为这使用了连接表达式。因此,它必须读取两个表的每一行,以评估表达式,然后才能判断连接是否满足。

因此,如果您可以为两个表添加一个额外的列作为日期(没有时间)并索引这些列,那会好得多。

ALTER TABLE electrical_readings ADD COLUMN date_read DATE, ADD KEY (date_read);
UPDATE electrical_readings SET date_read = DATE(FROM_UNIXTIME(time_read));

ALTER TABLE hourly_weather ADD COLUMN date_read DATE, ADD KEY (date_read);
UPDATE hourly_weather SET date_read = DATE(FROM_UNIXTIME(time_read));

SELECT r.date_read, 
  SUM(r.kwh) AS sumkwh, MAX(hw.temp) AS temp
FROM electrical_readings r
LEFT OUTER JOIN hourly_weather hw
  ON r.date_read = hw.date_read 
  AND hw.meter = 1
WHERE r.id = 1
GROUP BY r.date_read
HAVING temp IS NOT NULL

无论如何,添加SELECT *到这些查询中的任何一个都不是一个好主意,因为结果将是任意的。


回复您的评论,对不起,总和乘以 hourly_weather 中匹配的行数。

我们可以通过在派生表子查询中对 hourly_weather 进行聚合来弥补。

SELECT r.date_read, 
  SUM(r.kwh) AS sumkwh, hw.temp
FROM electrical_readings r
LEFT OUTER JOIN (
  SELECT date_read, MAX(temp) AS temp
  FROM hourly_weather
  WHERE meter = 1
  GROUP BY date_read) AS hw
    ON r.date_read = hw.date_read 
WHERE r.id = 1
GROUP BY r.date_read
HAVING temp IS NOT NULL

最好在 hourly_weather 上创建一个索引:

ALTER TABLE hourly_weather ADD KEY (date_read, meter, temp);
于 2013-04-15T17:15:50.833 回答