2013-04-15 97 views
1

我的表:寻找最高温度为某一天在SQL

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 != ''; 
+0

尝试运行没有外部查询选择;速度增益是多少?在我看来,它已经会提高你的表现。另一种解决方案可能是在那天后的cron期间存储这两天重要的值。那些价值不会改变(或者他们会)? – Luceos

+0

删除外部选择对查询运行时几乎没有影响。 –

+0

如果我删除子查询中的AND time_read> = datey子句,它将删除99%的运行时间。 –

回答

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); 
+0

以前我曾经有过很大的改进。干杯。 –

+0

这并不像预期的那样有效,它似乎在使得这张照片远远超过它应有的。如果我删除左外连接,则没有问题。 –

+0

我想我已经发现了这个问题,在“hourly_weather”表中每天有24个读数。如果我把你的查询给我的和数除以24,我就得到实际的和数。无论如何要补救这一点,没有任何东西如此武断? –

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最后一刻一切。

希望这有助于你

+0

+1仅仅用于帮助某人写出如此长的查询的所有努力 – Webnet

+0

如果我只想要一天的最高温度,这将会很棒。我想看看4/1/2013-22deg,4/2/2012-24deg,4/3/2012-18deg。等等等等。我的查询是找出所有电子读数拍摄日子的最高温度。 –

+0

所以你说对两个结果集进行查询,并用PHP对它们进行循环以合并它们?可以,但我希望有一个优雅的SQL解决方案。这是很多的PHP阵列排序和whatnot,我不会指望它比我当前的查询老实说:/ –