2013-04-15 22 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,我不會指望它比我當前的查詢老實說:/ –