2012-11-14 53 views
1

這是我在一個更大的SQL腳本中的子查詢。它在多個不同的CASE語句中執行相同的操作,所以我希望我能以某種方式組合這個動作,所以它不必一遍又一遍地做同樣的事情。但是,如果將ORDER BY命令移到CASE語句之外,我無法得到正確的結果。優化類似的MySQL子查詢

我在JDAY上加入了2個表格met_data和flexgridlayers_table。 Flexgridlayers_table具有JDAY和Segment的字段,met_data具有JDAY,TAIR和TDEW字段(在這個簡單示例中,實際上是更多字段)。我通過Matlab運行這個,所以變量1變量2是由嵌套循環設置的值。我需要使用CASE語句來說明變量1不等於1的情況,那麼我想輸出0.否則,我想查找與JDAY連接對應的值,但這些值可能不完全匹配F.JDAY和M.JDAY。我想匹配最接近的< =值,所以我在每個子查詢中使用ORDER BY M.JDAY DESC LIMIT 1語句。

輸出是一個包含字段JDAY(來自F.JDAY),TAIR和TDEW的表格。每當我嘗試移動CASE語句之外的ORDER BY部分來擺脫重複的子查詢時,我只得到一行結果來表示最大的JDAY。這個查詢給了我正確的結果 - 有沒有一種方法來優化這個?

SELECT F.JDAY, 
    CASE 
     WHEN *variable1*<>1 THEN 0 
     ELSE 
      (SELECT M.TAIR 
      FROM met_data AS M 
      WHERE M.Year=2000 AND M.JDAY<=F.JDAY 
      ORDER BY M.JDAY DESC LIMIT 1) 
    END AS TAIR, 
    CASE 
     WHEN *variable1*<>1 THEN 0 
     ELSE     
      (SELECT M.TDEW 
      FROM met_data AS M 
      WHERE M.Year=2000 AND M.JDAY<=F.JDAY 
      ORDER BY M.JDAY DESC LIMIT 1) 
    END AS TDEW 
FROM FlexGridLayers_table AS F 
WHERE F.SEGMENT=*variable2* 

進一步解釋:

該查詢將從flexgridlayers_table翻出所有JDAY值,然後將表met_data內搜索以找到對應於該表中最接近< = JDAY值的值。例如,請考慮以下flexgridlayers_table和met_data表:

flexgridlayers_table: 
Segment JDAY 
2  1.5 
2  2.5 
2  3.5 
3  1.5 
3  2.5 
3  3.5 

met_data: 
JDAY Year TAIR TDEW 
1.0 2000 7  8 
1.1 2000 9  10 
1.6 2000 11 12 
2.5 2000 13 14 
2.6 2000 15 16 
3.4 2000 17 18 
4.0 2000 19 20 

我想(和什麼上面返回查詢)會是這樣,對於變量1 = 1和變量2 = 2:

JDAY TAIR TDEW 
1.5 9  10 
2.5 13 14 
3.5 17 18 

我只是想知道是否有更有效的方式來編寫此查詢,所以我沒有對每個TAIR,TDEW等字段反覆執行相同的JDAY值列表上的ORDER BY命令。

+0

http://stackoverflow.com/questions/12925140/how-to-estimate-sql-query-timing/12925406#12925406 – felipsmartins

+0

此查詢需要32秒5個子查詢和* variable1 * = 1。我不確定還有什麼可以從您的鏈接中獲取... – Amy

+0

請發佈此查詢的解釋。 – Michael

回答

2

然後,我會寫如下...它看起來像你正在尋找一個「TAIR」和「TDEW」每個JDAY。如果是這種情況,請在年度情況下將LEFT JOIN應用於您的met_data表,並將F vs M JDay值應用於此表。現在通常情況下,這將每「JDay」返回多行

SELECT 
     PQ.JDay, 
     PQ.MaxJDayPerFDay, 
     CASE WHEN *var1* <> 1 THEN 0 ELSE M2.TAIR END TAIR, 
     CASE WEHN *var1* <> 1 THEN 0 ELSE M2.TDEW END TDEW 
    from 
     (SELECT 
       F.JDay, 
       MAX(M.JDAY) as MaxJDayPerFDay 
      from 
       FlexGridLayers_Table F 
       JOIN met_Data M 
        ON M.Year = 2000 
        AND F.JDay >= M.JDay 
      where 
       F.Segment = *var2* 
      group by 
       F.JDay) PQ 
     JOIN Met_Data M2 
      on M2.Year = 2000 
      AND PQ.MaxJDayPerFDay = M2.JDay 

現在這樣做預查詢在一旦met_data和組通過JDay應用MAX()JDay所以它總是會返回每個F一個記錄.JDay。所以,現在您有一個查詢爲您的F.Segment =變量2預先定義了資格。如果您需要從「F」表獲得其他列,請根據需要將它們放入此「PreQuery」(PQ別名)中。

然後,這個結果可以立即連接回met_data表,因爲現在可以從預查詢中明確知道一天的值。因此,您現在可以同時獲得TAIR和TDEW值,而不是爲每條記錄應用兩個單獨的查詢。

希望這是有道理的,如果沒有,讓我知道。

+0

工程太棒了!計算時間從32秒減少到2秒...不錯!我甚至沒有想過使用羣組 – Amy