нужна помощь в добавлении столбца в одну таблицу с помощью функции, которая выполняет арифметические операции между столбцами из двух отдельных таблиц

Я пытаюсь добавить столбец «wOBA» в таблицу «starting_pitcher_stats» в MySQL, используя сиквел-про. Ниже приведен код функции, выполняющей арифметические операции над девятью переменными в таблице «starting_pitcher_stats». В частности, функция собирает значения ряда переменных, применяет разные веса (коэффициенты) к некоторым из них (числитель ниже) и делит эту сумму путем сложения и вычитания еще нескольких переменных. Все эти переменные находятся в таблице «starting_pitcher_stats». Арифметические операции выражены в приведенной ниже формуле (коэффициенты — это значения, умноженные на каждую из переменных в числителе ниже):

wOBA=(0,69*ходьба_a + 0,72*HBP + 0,89*одиночный_a + 1,27*двойной_a + 1,62*тройной_a+ 2,10*HR_a)/(at_bats+ходьба_a+SF+HBP)

Каждый вес меняется в зависимости от года. Различные веса для каждого года взяты из таблицы «GUTS».

Первая дилемма, с которой я столкнулся, это получение правильного кода для функции. Во-вторых, правильный синтаксис кода, используемый для фактического вызова этой функции и заполнения нового столбца правильными взвешенными значениями wOBA для каждой игры каждого года (сезона) для каждого «Starting_Pitcher».

Функция создается с помощью приведенного ниже кода и указана как функция «wOBA» в моем списке функций и процедур. Однако маленькое колесо/ручка рядом с названием функции в сиквеле про почему-то неактивно. Только когда я узнаю правильный код для его вызова, я узнаю, есть ли какие-либо ошибки.

Пожалуйста, запросите любую дополнительную информацию, которую я могу предоставить, чтобы прояснить что-либо.

Заранее спасибо.

DELIMITER $$
    CREATE FUNCTION wOBA(wOBA DECIMAL(10,3))
    RETURNS DECIMAL(10,3)
    BEGIN
        DECLARE wOBA decimal(10,3);
        SET wOBA = 0;
        SELECT cast((SELECT SUM(weighted_BB) as wBB_sum 
            FROM (
                SELECT g.wBB*SUM(if(e.event_CD=14,1,0)) as weighted_BB 
                FROM events e 
                INNER JOIN GUTS g 
                    ON substring(e.game_ID,4,4)=g.season 
                WHERE PIT_ID=Starting_Pitcher 
                GROUP BY g.season) 
            as walks_a)  
            + (SELECT SUM(weighted_HBP) as wHBP_sum 
            FROM (
                SELECT g.wHBP*SUM(if(e.event_CD=16,1,0)) as weighted_HBP 
                FROM events e 
                INNER JOIN GUTS g 
                    ON substring(e.game_ID,4,4)=g.season 
                WHERE PIT_ID=Starting_Pitcher 
                GROUP BY g.season) 
            as HBP)     
            + (SELECT SUM(weighted_1B) as w1B_sum 
            FROM (
                SELECT g.w1B*SUM(if(e.event_CD=20,1,0)) as weighted_1B 
                FROM events e 
                INNER JOIN GUTS g 
                    ON substring(e.game_ID,4,4)=g.season 
                WHERE PIT_ID=Starting_Pitcher 
                GROUP BY g.season) 
            as singles_a)       
            + (SELECT SUM(weighted_2B) as w2B_sum 
            FROM ( 
                SELECT g.w2B*SUM(if(e.event_CD=21,1,0)) as weighted_2B 
                FROM events e 
                INNER JOIN GUTS g 
                    ON substring(e.game_ID,4,4)=g.season 
                WHERE PIT_ID=Starting_Pitcher 
                GROUP BY g.season) 
            as doubles_a)       
            + (SELECT SUM(weighted_3B) as w3B_sum 
            FROM (
                SELECT g.w3B*SUM(if(e.event_CD=22,1,0)) as weighted_3B 
                FROM events e 
                INNER JOIN GUTS g 
                    ON substring(e.game_ID,4,4)=g.season 
                WHERE PIT_ID=Starting_Pitcher 
                GROUP BY g.season) 
            as triples_a)       
            + (SELECT SUM(weighted_HR) as wHR_sum 
            FROM (
                SELECT g.wHR*SUM(if(e.event_CD=23,1,0)) as weighted_HR 
                FROM events e 
                INNER JOIN GUTS g 
                    ON substring(e.game_ID,4,4)=g.season 
                WHERE PIT_ID=Starting_Pitcher 
                GROUP BY g.season) 
            as HR_a) as decimal(10,3))
            /
            cast(SUM(if(e.ab_fl="T",1,0)) 
                + SUM(if(e.event_cd=14,1,0)) 
                + SUM(if(e.SF_fl="T",1,0)) 
                + SUM(if(e.event_cd=16,1,0)) as unsigned) INTO wOBA 
            FROM events e
            WHERE e.PIT_ID=Starting_Pitcher AND PIT_START_FL = "T"
            LIMIT 1;
        RETURN wOBA;
    END
    $$
    DELIMITER ;

Дарвин, Вот два скриншота таблицы events. Первый касается структуры, а второй — части контента (поскольку не весь контент вписывается в кадр):

[структура таблицы событий[1]

содержимое таблицы событий

Вот скриншоты структуры и содержимого таблицы GUTS.

введите здесь описание изображения

введите здесь описание изображения

Вот скриншот структуры таблицы событий, показывающий поля (и их определения) в функции:

введите здесь описание изображения

Обновлять:

UPDATE retrosheet.starting_pitcher_stats 
SET starting_pitcher_stats.wOBA =(SELECT
(
   (g.wBB * SUM(IF(e.event_cd = 14, 1, 0)))
   + (g.wHBP * SUM(IF(e.event_cd = 16, 1, 0)))
   + (g.w1B  * SUM(IF(e.event_cd = 20, 1, 0)))
   + (g.w2B  * SUM(IF(e.event_cd = 21, 1, 0)))
   + (g.w3B  * SUM(IF(e.event_cd = 22, 1, 0)))
   + (g.wHR  * SUM(IF(e.event_cd = 23, 1, 0)))
   )
   /
   (
     SUM(IF(e.ab_fl = 'T',   1, 0))
   + SUM(IF(e.event_cd = 14, 1, 0))
   + SUM(IF(e.sf_fl = 'T',   1, 0))
   + SUM(IF(e.event_cd = 16, 1, 0))
  ) AS wOBA
  FROM events AS e, GUTS AS g
  WHERE e.YEAR_ID = g.SEASON_ID
    AND e.PIT_START_FL= 'T'
    AND e.PIT_ID = Starting_Pitcher)

Запрос просто продолжает работать. Я буду продолжать настраивать его.

обновление: скриншоты таблицы startup_pitcher_stats введите здесь описание изображения

введите здесь описание изображения

Обновлять:

Хорошо, я пытаюсь просто создать столбец wOBA как часть новой таблицы со столбцами для других компонентов wOBA.

Но запрос просто продолжается вечно. Как сократить время выполнения?

DROP TABLE IF EXISTS starting_pitcher_wOBA;
CREATE TABLE starting_pitcher_wOBA 
SELECT
a.YEAR_ID
,
a.GAME_ID
,
a.PIT_ID
,
a.wBB
,
a.wHBP
,
a.w1B
,
a.w2B
,
a.w3B
,
a.wHR
,
a.u_walks_a
,
a.HBP
,
a.singles_a
,
a.doubles_a
,
a.triples_a
,
a.HR_a
,
a.at_bats
,
a.sacrifice_flies_a
,
a.wOBA
FROM
(
SELECT 
g.YEAR_ID
,
h.GAME_ID
,
e.PIT_ID
,
g.wBB
,
g.wHBP
,
g.w1B
,
g.w2B
,
g.w3B
,
g.wHR
,
SUM(IF(e.event_cd = 14, 1, 0)) AS u_walks_a
,
SUM(IF(e.event_cd = 16, 1, 0)) AS HBP
,
SUM(IF(e.event_cd = 20, 1, 0)) AS singles_a
,
SUM(IF(e.event_cd = 21, 1, 0)) AS doubles_a
,
SUM(IF(e.event_cd = 22, 1, 0)) AS triples_a
,
SUM(IF(e.event_cd = 23, 1, 0)) AS HR_a
,
SUM(IF(e.ab_fl = 'T',   1, 0)) AS at_bats
,
SUM(IF(e.sf_fl = 'T',   1, 0)) AS sacrifice_flies_a
,
(
(
   (g.wBB * SUM(IF(e.event_cd = 14, 1, 0))) 
   + (g.wHBP * SUM(IF(e.event_cd = 16, 1, 0))) 
   + (g.w1B  * SUM(IF(e.event_cd = 20, 1, 0))) 
   + (g.w2B  * SUM(IF(e.event_cd = 21, 1, 0))) 
   + (g.w3B  * SUM(IF(e.event_cd = 22, 1, 0))) 
   + (g.wHR  * SUM(IF(e.event_cd = 23, 1, 0))) 
   )
   /
   (
     SUM(IF(e.ab_fl = 'T',   1, 0)) 
   + SUM(IF(e.event_cd = 14, 1, 0)) 
   + SUM(IF(e.sf_fl = 'T',   1, 0)) 
   + SUM(IF(e.event_cd = 16, 1, 0)) 
  ) 
 )  AS wOBA
FROM events AS e, GUTS AS g, game AS h
WHERE e.PIT_START_FL= 'T' 
GROUP BY g.YEAR_ID, h.GAME_ID,e.PIT_ID) AS a
INNER JOIN GUTS AS g
ON 
a.YEAR_ID=g.YEAR_ID
INNER JOIN game AS h
ON
a.GAME_ID = h.GAME_ID
INNER JOIN events AS e
ON
a.PIT_ID = e.PIT_ID

person LeeZee    schedule 30.12.2015    source источник
comment
Есть ли у GUTS только одна запись за сезон, и мы выполняем этот расчет для нескольких сезонов?   -  person Darwin von Corax    schedule 31.12.2015
comment
В пункте WHERE PIT_ID=Starting_Pitcher откуда берутся эти два значения?   -  person Darwin von Corax    schedule 31.12.2015
comment
Привет, Дарвин, да, у GUTS есть один рекорд за сезон.   -  person LeeZee    schedule 31.12.2015
comment
«PIT_ID» берется из таблицы событий, а «Starting_Pitcher» — из таблицы «starting_pitcher_stats».   -  person LeeZee    schedule 31.12.2015
comment
Как выглядит таблица events?   -  person Darwin von Corax    schedule 31.12.2015
comment
Дарвин, я добавил скриншоты структуры и содержимого событий и таблиц GUTS в исходный пост... Как только я разберусь с кодом функции, я планировал создать процедуру, подобную той, с которой вы мне помогли, с целью создание полей накопления (общего количества), чтобы затем иметь значения сезона до даты для wOBA для каждой игры каждого года для каждого стартового питчера.   -  person LeeZee    schedule 31.12.2015
comment
Ваш запрос ссылается на некоторые столбцы в events, которые я не вижу в определении таблицы.   -  person Darwin von Corax    schedule 31.12.2015
comment
Дарвин, я добавил еще один скриншот структуры таблицы, показывающий столбцы, на которые есть ссылки в запросе. Я предполагаю, что столбцы в запросе, которые не были видны на исходном снимке экрана, — это то, что вы имеете в виду под теми, которые вы не можете видеть в определении таблицы. В противном случае я могу опубликовать скриншот таблицы startup_pitcher_stats, в которую я добавил столбцы с тех пор, как вы в последний раз работали над ней. Надеюсь, это то, о чем вы просили. Если нет, пожалуйста, дайте мне знать.   -  person LeeZee    schedule 01.01.2016
comment
Это то, о чем я просил, но я хотел бы видеть новые столбцы в starting_pitcher_stats сейчас.   -  person Darwin von Corax    schedule 09.01.2016
comment
Darwin, я добавил скрины таблицы startup_pitcher_stats   -  person LeeZee    schedule 09.01.2016


Ответы (1)


Мы начнем с очистки запроса. Вы всегда должны пытаться выполнять свои вычисления для каждой строки, когда это возможно, а не выполнять несколько вертикальных подзапросов, поскольку это позволяет избежать многократных проходов СУБД по одной и той же таблице.

SELECT
  (
   ( (g.wbb  * SUM(IF(e.event_cd = 14, 1, 0)))
   + (g.whbp * SUM(IF(e.event_cd = 16, 1, 0)))
   + (g.w1b  * SUM(IF(e.event_cd = 20, 1, 0)))
   + (g.w2b  * SUM(IF(e.event_cd = 21, 1, 0)))
   + (g.w3b  * SUM(IF(e.event_cd = 22, 1, 0)))
   + (g.whr  * SUM(IF(e.event_cd = 23, 1, 0)))
   )
   /
   (
     SUM(IF(e.ab_fl = 'T',   1, 0))
   + SUM(IF(e.event_cd = 14, 1, 0))
   + SUM(IF(e.sf_fl = 'T',   1, 0))
   + SUM(IF(e.event_cd = 16, 1, 0))
   )
  ) AS woba
  FROM events e, guts g
  WHERE e.year_id = g.season_id
    AND e.pit_start_fl = 'T'
    AND e.pit_id = starting_pitcher
  GROUP BY g.season;

Предполагая, что я где-то не пропустил запятую, это вернет столбец woba для каждого года для указанного стартового питчера.

Обратите внимание, что я присоединился к таблицам на e.year_id вместо SUBSTRING(e.game_ID,4,4); это позволяет избежать накладных расходов на вызов SUBSTRING() для каждой записи. Такого рода вещи кажутся незначительными, но они могут быстро складываться на большом столе.

Этого должно быть достаточно, чтобы вы начали.

person Darwin von Corax    schedule 07.01.2016
comment
Спасибо Дарвин! когда я запускаю его, я получаю сообщение об ошибке неизвестного столбца Starting_Pitcher в предложении where. Затем я понял, что мне нужно определить таблицу, в которую я хочу заполнить wOBA. См. OP, где я добавляю код UPDATE к вашему для заполнения столбца. запрос продолжает работать и работать. Я буду продолжать пытаться играть с ним. Когда я пробую это с GROUP by g. SEASON_ID в конце выдает ошибку. - person LeeZee; 09.01.2016
comment
Я добавил скриншот структуры таблицы start_pitcher_stats в исходный пост выше. - person LeeZee; 09.01.2016
comment
Дарвин, что вы думаете о моей попытке выше создать столбец wOBA как часть создания новой таблицы со столбцами для wOBA, а также для переменных, составляющих wOBA? Проблема в том, что запрос занимает вечность. Любые мысли о том, как я могу сделать процесс более эффективным? У меня уже есть столбцы в таблице startup_pitcher_stats для u_walks_a, singles_a, doubles_a, trips_a, HR_a, HBP, at_bats и жертвоприношения_flies_a. Было бы быстрее, если бы я извлекал данные из этих столбцов, а не извлекал их из таблицы событий? Спасибо. - person LeeZee; 11.01.2016