2016-05-14 43 views
0

我努力確定MySQL代碼創建列(平均park_factor)在我的表「starting_pitcher_stats」,我' d喜歡在另一列(park_factor)中包含季節到季節的最新季節平均值。我希望這個賽季平均水平可以通過投手和按日期分組。試圖創建與同一表中的另一列的值的季節到最新平均值使用MySQL

理想的情況下,該表是這樣的:

pitcher  park_fac avg_park_fac  date 
    aased001 94   94   1977-07-31 
    aased001 100  97   1977-08-06 
    aased001 108  100.666  1977-08-11 
    aased001 108  102.5  1977-08-16 
    aased001 96   101.2  1977-08-21 
    aased001 108  102.33  1977-08-26 
    aased001 108  103.14  1977-08-31 
    aased001 104  103.25  1977-09-05 
    aased001 108  103.77  1977-09-10 
    aased001 92   102.6  1977-09-16 
    aased001 106  102.9  1977-09-22 
    aased001 108  103.33  1977-09-27 

我正在使用的代碼是:

SELECT Starting_Pitcher, full_park_factor, AVG(full_park_factor), Game_Date 
FROM starting_pitcher_stats 
GROUP BY Starting_Pitcher, Game_Date, Game_Number 

...產生的表的樣本如下:

pitcher  park_fac avg_park_fac date 
aased001 94   94.0000  1977-07-31 
aased001 100  100.0000  1977-08-06 
aased001 108  108.0000  1977-08-11 
aased001 108  108.0000  1977-08-16 
aased001 96   96.0000  1977-08-21 
aased001 108  108.0000  1977-08-26 
aased001 108  108.0000  1977-08-31 
aased001 104  104.0000  1977-09-05 
aased001 108  108.0000  1977-09-10 
aased001 92   92.0000  1977-09-16 
aased001 106  106.0000  1977-09-22 
aased001 108  108.0000  1977-09-27 

有人可以幫忙嗎?

非常感謝您的幫助。 李

+1

我不知道你想讓我們幫你什麼。考慮提供適當的CREATE和INSERT語句對應於所需的結果 – Strawberry

+0

您好草莓,我只是想創建一個列avg_Park_factor,具有相應的行值的平均值+ park_factors列。 – LeeZee

回答

2

你需要加入你的表在同一個投手從同一個表中的所有以前的結果。

我不太清楚你如何定義你的季節,但假設它是以日曆年爲單位的,下面的查詢產生所需的輸出。

SELECT 
    a.Starting_Pitcher, a.full_park_factor, 
    AVG(b.full_park_factor), a.Game_Date, a.Game_Number 
FROM starting_pitcher_stats a 
INNER JOIN starting_pitcher_stats b 
    ON a.Starting_Pitcher = b.Starting_Pitcher 
    AND (b.Game_Date < a.Game_Date OR 
     (b.Game_Date = a.Game_Date AND b.Game_Number <= a.Game_Number)) 
    AND YEAR(b.Game_Date) = YEAR(a.Game_Date) 
GROUP BY a.Starting_Pitcher, a.Game_Date, a.Game_Number; 

您似乎想要使用此計算結果更新表中的列。這可以通過觸發器進行實時更新來實現,該觸發器在插入或更新現有數據或使用視圖時更新列。

CREATE VIEW starting_pitcher_stats_with_average AS 
SELECT 
    a.Starting_Pitcher, a.full_park_factor, 
    AVG(b.full_park_factor), a.Game_Date, a.Game_Number 
FROM starting_pitcher_stats a 
INNER JOIN starting_pitcher_stats b 
    ON a.Starting_Pitcher = b.Starting_Pitcher 
    AND (b.Game_Date < a.Game_Date OR 
     (b.Game_Date = a.Game_Date AND b.Game_Number <= a.Game_Number)) 
    AND YEAR(b.Game_Date) = YEAR(a.Game_Date) 
GROUP BY a.Starting_Pitcher, a.Game_Date, a.Game_Number; 

在你自己的答案,你創建一個過程來更新表中的一氣呵成的所有記錄均列,所以也許你不想當你插入數據有列的更新,但僅僅是能夠按需添加所有行的平均值。在這種情況下,您可以編寫包含上述SELECT查詢的UPDATE語句作爲子查詢。由於MySQL不能爲UPDATE和子查詢使用相同的表,因此必須將子查詢包裝到另一個SELECT中,以便MySQL根據結果生成臨時表。

UPDATE starting_pitcher_stats c 
SET c.std_F_parkfactor = (
    SELECT d.std_F_parkfactor FROM (
     SELECT 
      a.Starting_Pitcher, 
      AVG(b.full_park_factor) std_F_parkfactor, 
      a.Game_Date, a.Game_Number 
     FROM starting_pitcher_stats a 
     INNER JOIN starting_pitcher_stats b 
      ON a.Starting_Pitcher = b.Starting_Pitcher 
      AND (b.Game_Date < a.Game_Date OR 
       (b.Game_Date = a.Game_Date 
        AND b.Game_Number <= a.Game_Number)) 
      AND YEAR(b.Game_Date) = YEAR(a.Game_Date) 
     GROUP BY a.Starting_Pitcher, a.Game_Date, a.Game_Number 
    ) d 
    WHERE c.Starting_Pitcher = d.Starting_Pitcher 
    AND c.Game_Date = d.Game_Date 
    AND c.Game_Number = d.Game_Number 
); 
+0

是的,我認爲就是這樣 - 倒數第二行可能也可能不需要 – Strawberry

+0

Matt,謝謝!這很好。現在嘗試使用「ALTER TABLE starting_pitcher_stats ADD COLUMN AVG(b.full_park_factor)」添加AVG(b.full_park_factor)字段作爲列的表,但它不起作用... Game_Number列僅指遊戲數如果在給定的日期發生了雙頭(即,0 =遊戲1; 1 =如果發生了雙頭遊戲的遊戲1; 2 =雙頭遊戲2)但是我可以將該列添加到代碼中。謝謝。 – LeeZee

+0

MySQL [不支持在默認值中使用表達式](http://stackoverflow.com/questions/270309/can-i-use-a-function-for-a-default-value- in-mysql)你可以編寫一個觸發器來更新插入表中的一列,但只有當你總是以日期順序輸入統計信息時纔會起作用,一旦你錯過了一個並稍後輸入,你必須更新表中的所有以下記錄:最好查看創建[來自'SELECT'語句]的視圖(http://dev.mysql.com/doc/refman/5.7/en/create-view。 html)取決於o n你的要求。 –

0

更新:這是存儲賽季至今(以季)給定季節的公園係數平均在一列,在這種情況下是另一列的值的平均值的方法使用存儲過程的同一個表。它實際上是通過除以row_number來計算平均值,row_number對應於計算此變量時已循環的值的行數。如果您已經收集了您想要一次更新或很少更新的數據,但如Matt Raines所暗示的,可能需要比他建議的方法更頻繁地運行,這種方法纔有效。如果表格會每天至少一次使用連續幾天比賽結果的數據更新,我認爲使用他的方法會減少勞動力密集度。請讓我知道什麼是可以被消除:

DROP PROCEDURE IF EXISTS std_park_factor_avg; 
DELIMITER $$ 
CREATE PROCEDURE std_park_factor_avg() 
BEGIN 
    DECLARE pit_id CHAR(10); 
    DECLARE lgID CHAR (2); 
    DECLARE YEARID INT; 
    DECLARE gdate DATE; 
    DECLARE seq INT; 
    DECLARE F_park_factor INT; 
    DECLARE RNUMBER INT; 
    DECLARE accum_F_parkfactor REAL; 
    DECLARE accum_row_number INT; 
    DECLARE accum_avg_F_parkfactor REAL; 
    DECLARE prev_year YEAR(4); 
    DECLARE end_of_cursor BOOLEAN; 

    DECLARE no_table CONDITION FOR SQLSTATE '42S02'; 

    DECLARE c1 CURSOR FOR 
     SELECT Starting_Pitcher, lg_ID, YEAR_ID, Game_Date, Game_Number, full_park_factor, ROW_NUMBER 
     FROM starting_pitcher_stats 
     GROUP BY Starting_Pitcher, lg_ID, YEAR_ID, Game_Date, Game_Number; 

    DECLARE CONTINUE HANDLER FOR NOT FOUND 
     SET end_of_cursor := TRUE; 

    SET end_of_cursor := FALSE; -- reset 
    SET prev_year := 0;   -- reset control-break 

    OPEN c1; 

    fetch_loop: LOOP 
     FETCH c1 INTO pit_id, lgID, YEARID, gdate,seq, F_park_factor, RNUMBER; 
     IF end_of_cursor THEN 
     LEAVE fetch_loop; 
     END IF; 

     -- check control-break conditions 
     IF YEAR(gdate) != prev_year THEN 
     SET accum_F_parkfactor := 0.0; 
     SET RNUMBER:= 1.0; 
     SET accum_avg_F_parkfactor := 0.0; 
     SET prev_year := YEAR(gdate); 
     END IF; 

    SET accum_F_parkfactor := accum_F_parkfactor + F_park_factor; 
    SET accum_avg_F_parkfactor := accum_F_parkfactor/RNUMBER; 

     UPDATE starting_pitcher_stats 
     SET std_F_parkfactor =accum_avg_F_parkfactor 
     WHERE Starting_Pitcher = pit_id 
      AND lg_ID = lgID 
      AND YEAR_ID = YEARID 
      AND Game_Date = gdate 
      AND Game_Number = seq; 

    END LOOP; 
    CLOSE c1; 
    END 
$$ 

DELIMITER ; 
相關問題