How to SUM TIMEDIFF's During hours - mysql

I hope this can clearly explain what I am looking for. I have searched read through a few articles on this site, but haven't found what I am looking for. I have also spent close to 3 hours trying to figure this out on my own.
I am trying to count the number of records and SUM the WorkTime. Here is my query I have been working with.
SELECT Log.User
, sum(if(hour(endtime) = 0, 1, 0)) AS Midnight
, sum(if(hour(endtime) = 1, 1, 0)) AS `1AM`
, sum(if(hour(endtime) = 2, 1, 0)) AS `2AM`
, sum(if(hour(endtime) = 3, 1, 0)) AS `3AM`
, sum(if(hour(endtime) = 4, 1, 0)) AS `4AM`
, sum(if(hour(endtime) = 5, 1, 0)) AS `5AM`
, sum(if(hour(endtime) = 6, 1, 0)) AS `6AM`
, sum(if(hour(endtime) = 7, 1, 0)) AS `7AM`
, sum(if(hour(endtime) = 8, 1, 0)) AS `8AM`
, sum(if(hour(endtime) = 9, 1, 0)) AS `9AM`
, sum(if(hour(endtime) = 10, 1, 0)) AS `10AM`
, sum(if(hour(endtime) = 11, 1, 0)) AS `11AM`
, sum(if(hour(endtime) = 12, 1, 0)) AS `12PM`
, sum(if(hour(endtime) = 13, 1, 0)) AS `1PM`
, sum(if(hour(endtime) = 14, 1, 0)) AS `2PM`
, sum(if(hour(endtime) = 15, 1, 0)) AS `3PM`
, sum(if(hour(endtime) = 16, 1, 0)) AS `4PM`
, sum(if(hour(endtime) = 17, 1, 0)) AS `5PM`
, sum(if(hour(endtime) = 18, 1, 0)) AS `6PM`
, sum(if(hour(endtime) = 19, 1, 0)) AS `7PM`
, sum(if(hour(endtime) = 20, 1, 0)) AS `8PM`
, if(hour(endtime) = 20, sec_to_time(sum(time_to_sec(endtime) - time_to_sec(starttime))), 0) AS `8PM Time`
, sum(if(hour(endtime) = 21, 1, 0)) AS `9PM`
, sum(if(hour(endtime) = 22, 1, 0)) AS `10PM`
, sum(if(hour(endtime) = 23, 1, 0)) AS `11PM`
FROM
(
SELECT user
, controlnumber
, starttime
, endtime
, timediff(endtime, starttime) AS Worktime
FROM
atrtaxcert.ordertimeworked
) AS Log
GROUP BY
Log.User;
These start and end times are only minutes apart.
Any guidance is much appreciated. This is my first post here, and was not able to provide any images to help describe.

If starttime and endtime are TIME datatypes, then use the TIME_TO_SEC function and do a subtraction. Total up the seconds, and then convert the total to a string representation.
SELECT `Log`.`User`
, ...
, SUM(HOUR(`Log`.endtime)=20) AS `8PM_count`
, SUM(IF(HOUR(`Log`.endtime)=20,work_seconds,0) AS `8PM_seconds`
, SEC_TO_TIME(SUM(IF(HOUR(`Log`.endtime)=20,`Log`.work_seconds,0) AS `8PM_hhhmmss`
, ...
FROM ( SELECT
, TIME_TO_SEC(endtime)-TIME_TO_SEC(starttime) AS work_seconds
) `Log`
GROUP
BY `Log`.`User`
NOTE: this:
SELECT HOUR(endtime)=0 AS foo
is shorthand equivalent to
SELECT IF(HOUR(endtime) = 0, 1, 0) AS foo
If starttime and endtime are DATETIME values, the you can use the TIMESTAMPDIFF function to calculate the difference in seconds:
SELECT `Log`.`User`
, ...
, SUM(HOUR(`Log`.endtime)=20) AS `8PM_count`
, SUM(IF(HOUR(endtime)=20,TIMESTAMPDIFF(SECOND,`Log`.starttime,`Log`.endtime),0) AS `8PM_seconds`
, ...
FROM (
) `Log`
GROUP
BY `Log`.`User`
(You probably want to ignore the values returned when e.g. starttime = '23:59:00' and endtime = '00:01:00', and that would require another conditional test.)

Related

SQL query to break down day by day for entire week

I have a table of sales in MySQL. I'm trying in 1 query to get a view that looks like this:
AGENT, MONDAY_TOTAL, TUESDAY_TOTAL,WEDNESDAY_TOTAL,THURSDAY_TOTAL,FRIDAY_TOTAL,SATURDAY_TOTAL
What I have so far is this:
SELECT DISTINCT(repname), DAYOFWEEK(sub_date), COUNT(*)
FROM `NewDeals`
WHERE WEEK(sub_date) = WEEK(CURRENT_DATE)
GROUP BY repname, DAYOFWEEK(sub_date)
That gives me values that look like this:
AGENT, DAYOFWEEK, TOTAL
Naturally, I can turn the output of the second example into the first in my code, but if I can just do it with the SQL query I'd rather do that.
SELECT repname,
SUM(IF(DAYOFWEEK(sub_date)=2, 1, 0)) AS MONDAY_TOTAL,
SUM(IF(DAYOFWEEK(sub_date)=3, 1, 0)) AS TUESDAY_TOTAL,
SUM(IF(DAYOFWEEK(sub_date)=4, 1, 0)) AS WEDNESDAY_TOTAL,
SUM(IF(DAYOFWEEK(sub_date)=5, 1, 0)) AS THURSDAY_TOTAL,
SUM(IF(DAYOFWEEK(sub_date)=6, 1, 0)) AS FRIDAY_TOTAL,
SUM(IF(DAYOFWEEK(sub_date)=7, 1, 0)) AS SATURDAY_TOTAL,
SUM(IF(DAYOFWEEK(sub_date)=1, 1, 0)) AS SUNDAY_TOTAL
FROM `NewDeals`
WHERE WEEK(sub_date) = WEEK(CURRENT_DATE)
GROUP BY repname
But getting results for days that haven't happened yet.
Update: This was because we did not constrain the year:
Solution:
SELECT repname,
SUM(IF(DAYOFWEEK(sub_date)=2, 1, 0)) AS MONDAY_TOTAL,
SUM(IF(DAYOFWEEK(sub_date)=3, 1, 0)) AS TUESDAY_TOTAL,
SUM(IF(DAYOFWEEK(sub_date)=4, 1, 0)) AS WEDNESDAY_TOTAL,
SUM(IF(DAYOFWEEK(sub_date)=5, 1, 0)) AS THURSDAY_TOTAL,
SUM(IF(DAYOFWEEK(sub_date)=6, 1, 0)) AS FRIDAY_TOTAL,
SUM(IF(DAYOFWEEK(sub_date)=7, 1, 0)) AS SATURDAY_TOTAL,
SUM(IF(DAYOFWEEK(sub_date)=1, 1, 0)) AS SUNDAY_TOTAL
FROM `NewDeals`
WHERE WEEK(sub_date) = WEEK(CURRENT_DATE) AND YEAR(sub_date) = YEAR(CURRENT_DATE)
GROUP BY repname
You can use an IF function to select only DAYOFWEEK-related counts, then sum every counted element inside the SUM aggregate function as follows:
SELECT repname,
SUM(IF(DAYOFWEEK(sub_date)=2, 1, 0)) AS MONDAY_TOTAL,
SUM(IF(DAYOFWEEK(sub_date)=3, 1, 0)) AS TUESDAY_TOTAL,
SUM(IF(DAYOFWEEK(sub_date)=4, 1, 0)) AS WEDNESDAY_TOTAL,
SUM(IF(DAYOFWEEK(sub_date)=5, 1, 0)) AS THURSDAY_TOTAL,
SUM(IF(DAYOFWEEK(sub_date)=6, 1, 0)) AS FRIDAY_TOTAL,
SUM(IF(DAYOFWEEK(sub_date)=7, 1, 0)) AS SATURDAY_TOTAL,
SUM(IF(DAYOFWEEK(sub_date)=1, 1, 0)) AS SUNDAY_TOTAL
FROM `NewDeals`
WHERE WEEK(sub_date) = WEEK(CURRENT_DATE)
GROUP BY repname
Note: when the DISTINCT keyword is applied, it will work on every selected field of your SELECT clause, you can't make a distinct of a single field using parentheses.

How to group output and create columns from results [duplicate]

I have a simple query that produces the below results:
SELECT month,transporttype,count(transporttype) as loads
from deliveries
group by month,transporttype
I would like to transpose the rows into columns.
I understand mysql does not have pivot functions so a union is required but not 100% sure.
Thanks in advance for the help.
You can do it with a crosstab like this -
SELECT
`year`,
`month`,
SUM(IF(`transporttype` = 'inbound', 1, 0)) AS `inbound`,
SUM(IF(`transporttype` = 'LocalPMB', 1, 0)) AS `LocalPMB`,
SUM(IF(`transporttype` = 'Long Distance', 1, 0)) AS `Long Distance`,
SUM(IF(`transporttype` = 'shuttle', 1, 0)) AS `shuttle`,
SUM(IF(`transporttype` = 'export', 1, 0)) AS `export`,
SUM(IF(`transporttype` = 'Extrusions-LongDistance', 1, 0)) AS `Extrusions-LongDistance`,
SUM(IF(`transporttype` = 'Extrusions-Shuttle', 1, 0)) AS `Extrusions-Shuttle`
FROM `deliveries`
GROUP BY `year`, `month`
On a different note, you should move transporttype values to a lookup table and have transporttype_id in this table.

Set column value when grouped record is null

I have the following query which returns rows grouped.
For the column mc_name which returns a NULL value, is there any way to set a value without changing records data?
This is the query:
select
megaagents.megaagent_name AS 'mc_name',
SUM(IF(MONTH(properties.created_at) = 1, 1, 0)) as ENE,
SUM(IF(month(properties.created_at) = 2, 1, 0)) AS FEB,
SUM(IF(month(properties.created_at) = 3, 1, 0)) as MAR,
SUM(IF(month(properties.created_at) = 4, 1, 0)) AS ABR,
SUM(IF(month(properties.created_at) = 5, 1, 0)) AS MAY,
SUM(IF(month(properties.created_at) = 6, 1, 0)) as JUN,
SUM(IF(month(properties.created_at) = 7, 1, 0)) as JUL,
SUM(IF(month(properties.created_at) = 8, 1, 0)) AS AGO,
SUM(IF(month(properties.created_at) = 9, 1, 0)) as SEP,
SUM(IF(month(properties.created_at) = 10, 1, 0)) as OCT,
SUM(IF(month(properties.created_at) = 11, 1, 0)) as NOV,
SUM(IF(month(properties.created_at) = 12, 1, 0)) as DIC,
COUNT(PROPERTIES.PROP_EXCLUSIVE) AS TOTAL
from
`properties`
left join `megaagents` on `properties`.`megaagent_id` = `megaagents`.`id`
where
`properties`.`marketcenter_id` = 11
and `properties`.`prop_exclusive` in ('No Exclusiva', 'Exclusiva')
and `properties`.`prop_transaction` in ('Alquiler Temporal', 'Alquiler', 'Venta')
group by
`megaagents`.`megaagent_name`
order by
`megaagents`.`megaagent_name` asc
Regards!
Use COALESCE():
select
coalesce(megaagents.megaagent_name, 'custom value') AS mc_name,
....................................................................

optimizing mysql query with multiple sum(if(condition))

I have written a query which consists of multiple joins and sum(if()) condition.
I am using MySql Database.
The query structure seems like this:
*The query joins from multiple tables(7 to be precise) and the sum(if()) conditions is to represent total 53 states of US.*It takes almost 20 minutes for the query to execute which is a very long period.
If anyone could suggest how can I reduce this large amount of time.
SELECT ag.position_id AS 'position_id',
ag.npn AS 'NPN',
concat(ag.first_name, ' ', ag.last_name) AS 'full_name',
lb.name AS 'lob',
location_lic AS 'loc',
COUNT(DISTINCT lt.id) AS 'RTS_Total',
SUM(IF(st.id = 1, 1, 0)) AS 'AK',
SUM(IF(st.id = 2, 1, 0)) AS 'AL',
SUM(IF(st.id = 3, 1, 0)) AS 'AR',
SUM(IF(st.id = 4, 1, 0)) AS 'AZ',
SUM(IF(st.id = 5, 1, 0)) AS 'CA',
SUM(IF(st.id = 6, 1, 0)) AS 'CO',
SUM(IF(st.id = 7, 1, 0)) AS 'CT',
SUM(IF(st.id = 8, 1, 0)) AS 'DC',
SUM(IF(st.id = 9, 1, 0)) AS 'DE',
SUM(IF(st.id = 10, 1, 0)) AS 'FL',
SUM(IF(st.id = 11, 1, 0)) AS 'GA',
SUM(IF(st.id = 12, 1, 0)) AS 'HI',
SUM(IF(st.id = 13, 1, 0)) AS 'IA',
SUM(IF(st.id = 14, 1, 0)) AS 'ID',
SUM(IF(st.id = 15, 1, 0)) AS 'IL',
SUM(IF(st.id = 16, 1, 0)) AS 'IN',
SUM(IF(st.id = 17, 1, 0)) AS 'KS',
SUM(IF(st.id = 18, 1, 0)) AS 'KY',
SUM(IF(st.id = 19, 1, 0)) AS 'LA',
SUM(IF(st.id = 20, 1, 0)) AS 'MA',
SUM(IF(st.id = 21, 1, 0)) AS 'MD',
SUM(IF(st.id = 22, 1, 0)) AS 'ME',
SUM(IF(st.id = 23, 1, 0)) AS 'MI',
SUM(IF(st.id = 24, 1, 0)) AS 'MN',
SUM(IF(st.id = 25, 1, 0)) AS 'MO',
SUM(IF(st.id = 26, 1, 0)) AS 'MS',
SUM(IF(st.id = 27, 1, 0)) AS 'MT',
SUM(IF(st.id = 28, 1, 0)) AS 'NC',
SUM(IF(st.id = 29, 1, 0)) AS 'ND',
SUM(IF(st.id = 30, 1, 0)) AS 'NE',
SUM(IF(st.id = 31, 1, 0)) AS 'NH',
SUM(IF(st.id = 32, 1, 0)) AS 'NJ',
SUM(IF(st.id = 33, 1, 0)) AS 'NM',
SUM(IF(st.id = 34, 1, 0)) AS 'NV',
SUM(IF(st.id = 35, 1, 0)) AS 'NY',
SUM(IF(st.id = 36, 1, 0)) AS 'OH',
SUM(IF(st.id = 37, 1, 0)) AS 'OK',
SUM(IF(st.id = 38, 1, 0)) AS 'OR',
SUM(IF(st.id = 39, 1, 0)) AS 'PA',
SUM(IF(st.id = 40, 1, 0)) AS 'PR',
SUM(IF(st.id = 41, 1, 0)) AS 'RI',
SUM(IF(st.id = 42, 1, 0)) AS 'SC',
SUM(IF(st.id = 43, 1, 0)) AS 'SD',
SUM(IF(st.id = 44, 1, 0)) AS 'TN',
SUM(IF(st.id = 45, 1, 0)) AS 'TX',
SUM(IF(st.id = 46, 1, 0)) AS 'UT',
SUM(IF(st.id = 47, 1, 0)) AS 'VA',
SUM(IF(st.id = 48, 1, 0)) AS 'VI',
SUM(IF(st.id = 49, 1, 0)) AS 'VT',
SUM(IF(st.id = 50, 1, 0)) AS 'WA',
SUM(IF(st.id = 51, 1, 0)) AS 'WI',
SUM(IF(st.id = 52, 1, 0)) AS 'WV',
SUM(IF(st.id = 53, 1, 0)) AS 'WY'
FROM cxprtsapp_licensetracker lt
INNER JOIN cxprtsapp_agents ag ON ag.id = lt.agent_id_id AND ag.position_status LIKE 'Active'
LEFT JOIN cxprtsapp_statelobjit slj ON slj.state_id = lt.state_id_id AND ag.lob_id = slj.lob_id
LEFT JOIN
(select npn, rtsreport_appointed, rtsreport_licensed, state_id, lob_id
from cxprtsapp_rtslob
order BY refresh_number desc
) rts ON rts.state_id = lt.state_id_id and ag.lob_id = rts.lob_id and ag.npn=rts.npn
INNER JOIN cxprtsapp_location lc ON lc.id = ag.loc_id
INNER JOIN cxprtsapp_lineofbussiness lb ON lb.id = ag.lob_id
INNER JOIN cxprtsapp_states st ON st.id = lt.state_id_id
LEFT JOIN
(SELECT DISTINCT npn, state_code, status
FROM cxprtsapp_pdbappointments
WHERE status LIKE 'Appointed'
) appt ON appt.npn = ag.npn AND appt.state_code = st.state_code
WHERE certification_id IS NOT NULL
AND (expiration_date IS NULL OR expiration_date > CURDATE())
AND (slj.jit = 1 OR rts.rtsreport_appointed = 1 OR appt.status IS NOT NULL)
GROUP BY ag.id, ag.lob_id,loc_id ORDER BY ag.hire_date DESC;
Solution:
The time taken for the query has reduced from 10-15 min to 10-20 sec.
We must alter database index for performance.
we must the run the below sql query in the database first.
‌
ALTER TABLE cxprtsapp_agents ADD INDEX cxprtsapp_agents_idx_status_id_id_npn_id (position_status,id,lob_id,npn,loc_id);
ALTER TABLE cxprtsapp_licensetracker ADD INDEX cxprtsapp_licensetra_idx_id_id_id_id (agent_id_id,state_id_id,certification_id,id);
ALTER TABLE cxprtsapp_lineofbussiness ADD INDEX cxprtsapp_lineofbuss_idx_id_name (id,name);
ALTER TABLE cxprtsapp_location ADD INDEX cxprtsapp_location_idx_id_lic (id,location_lic);
ALTER TABLE cxprtsapp_statelobjit ADD INDEX cxprtsapp_statelobji_idx_id_id (state_id,lob_id);
ALTER TABLE cxprtsapp_states ADD INDEX cxprtsapp_states_idx_id_code (id,state_code);
ALTER TABLE cxprtsapp_rtslob ADD INDEX cxprtsapp_rtslob_idx_numbe_npn_appoi_licen_id_id (refresh_number,npn,rtsreport_appointed,rtsreport_licensed,state_id,lob_id);
ALTER TABLE cxprtsapp_pdbappointments ADD INDEX cxprtsapp_pdbappoint_idx_status_npn_code (status,npn,state_code);

need help adding column to one table using function that does arithmetic operations between columns from two separate tables

I am trying to add a column "wOBA" to a table "starting_pitcher_stats" in MySQL using sequel-pro. Below is the code for a function that performs arithmetic operations on nine variables in the "starting_pitcher_stats" table. In particular, the function gathers the values for a number of variables, applies different weights (coefficients) to some of them (numerator below) and divides that sum by the addition and subtraction of a few more variables. All of these variables reside in the "starting_pitcher_stats" table. The arithmetic operations are expressed in the below formula (the coefficients are the values that are multiplied by each of the variables in numerator below):
wOBA=(.69*walks_a + .72*HBP + .89*singles_a + 1.27*doubles_a + 1.62*triples_a+ 2.10*HR_a)/(at_bats+walks_a+SF+HBP)
Each weight varies by year. The different weights for each year come from the table "GUTS".
The first dilemma I'm having is getting the correct code for the function. The second is the correct code syntax to use to actually call up this function and populate the new column with correct weighted wOBA values for each game of each year(season) for each "Starting_Pitcher".
The function is created with the code below and is listed as a function "wOBA" in my list of functions and procedures. However, the little wheel/knob next to the function name in sequel pro is greyed-out for some reason. It's not until I find out the correct code to invoke it, that I'll know if there are any errors.
Please ask for any more information that I can provide to clarify anything.
Thank you in advance.
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 ;
Darwin, Here are two screen shots of the events table. The first is of the structure and the second is some of the content (as not all of the content fits into the shot):
[
Here are screenshots of the structure and contents of the GUTS table.
Here is a screenshot of the events table structure showing the fields (and their definitions)in the function:
Update:
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)
The query just keeps running. I'll keep tweaking it.
update:
screenshots of starting_pitcher_stats table
Update:
Ok, I'm trying to just create a wOBA column as part of a new table with columns for the other components of wOBA.
But, the query just goes on forever. How can I make the run-time shorter?
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
We'll start by cleaning up the query. You should always try to perform your calculations across each row when possible rather than performing multiple vertical subqueries, as this avoids the DBMS making multiple passes over the same table.
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;
Assuming I haven't dropped a comma somewhere, this will return a column woba for each year for the specified starting pitcher.
Note that I've joined the tables on e.year_id instead of SUBSTRING(e.game_ID,4,4); this avoids the overhead of calling SUBSTRING() on each record. This sort of thing seems minor, but it can add up quickly over a large table.
That should be enough to get you started.