Get rank in a score table - mysql

how to rank in myqsl?
sample code:
SELECT
contestant_tbl.contestant_num,
contestant_tbl.fn,
contestant_tbl.ln,
tally_j1_tbl.c1_score + tally_j1_tbl.c2_score AS j1_total,
tally_j2_tbl.c1_score + tally_j2_tbl.c2_score AS j2_total
FROM
contestant_tbl
LEFT JOIN tally_j1_tbl ON contestant_tbl.contestant_num = tally_j1_tbl.contestant_num
LEFT JOIN tally_j2_tbl ON contestant_tbl.contestant_num = tally_j2_tbl.contestant_num
GROUP BY
contestant_tbl.contestant_num
i wanted to have an additional column total and rank.

Hope this is what you are looking for.
SELECT
contestant_tbl.contestant_num,
contestant_tbl.fn,
contestant_tbl.ln,
tally_j1_tbl.c1_score + tally_j1_tbl.c2_score AS j1_total,
tally_j2_tbl.c1_score + tally_j2_tbl.c2_score AS j2_total
j1_total + j2_total AS total,
RANK () OVER (
ORDER BY total DESC
) rank
FROM
contestant_tbl
LEFT JOIN tally_j1_tbl ON contestant_tbl.contestant_num = tally_j1_tbl.contestant_num
LEFT JOIN tally_j2_tbl ON contestant_tbl.contestant_num = tally_j2_tbl.contestant_num
GROUP BY
contestant_tbl.contestant_num

We cannot guess your database structure according to your question. However, there are couple of noticeable issues.
Please take a look at the corrected query (rankings included):
set #num = 0;
SELECT
contestant_tbl.contestant_num,
contestant_tbl.fn,
contestant_tbl.ln,
sum(coalesce(tally_j1_tbl.c1_score, 0)) + sum(coalesce(tally_j1_tbl.c2_score, 0)) AS j1_total,
sum(coalesce(tally_j2_tbl.c1_score, 0)) + sum(coalesce(tally_j2_tbl.c2_score, 0)) AS j2_total,
sum(coalesce(tally_j1_tbl.c1_score, 0)) + sum(coalesce(tally_j1_tbl.c2_score, 0)) + sum(coalesce(tally_j2_tbl.c1_score, 0)) + sum(coalesce(tally_j2_tbl.c2_score, 0)) AS total,
#num := #num + 1 as pos
FROM
contestant_tbl
LEFT JOIN tally_j1_tbl ON contestant_tbl.contestant_num = tally_j1_tbl.contestant_num
LEFT JOIN tally_j2_tbl ON contestant_tbl.contestant_num = tally_j2_tbl.contestant_num
GROUP BY
contestant_tbl.contestant_num
ORDER BY
sum(coalesce(tally_j1_tbl.c1_score, 0)) + sum(coalesce(tally_j1_tbl.c2_score, 0)) + sum(coalesce(tally_j2_tbl.c1_score, 0)) + sum(coalesce(tally_j2_tbl.c2_score, 0))
Numerical values that can be NULL should be coalesced prior sum opperation. (e.g. coalesce(tally_j2_tbl.c2_score, 0)).
Your query contains group by, but doesn't contain any aggregate function. I assume that sum should be used.
Ranking is achieved by utilizing MySQL variables. It is for older MySQL versions. MySQL 8 introduced RANK function so it is easier and cleaner:
SELECT
contestant_tbl.contestant_num,
contestant_tbl.fn,
contestant_tbl.ln,
sum(coalesce(tally_j1_tbl.c1_score, 0)) + sum(coalesce(tally_j1_tbl.c2_score, 0)) AS j1_total,
sum(coalesce(tally_j2_tbl.c1_score, 0)) + sum(coalesce(tally_j2_tbl.c2_score, 0)) AS j2_total,
sum(coalesce(tally_j1_tbl.c1_score, 0)) + sum(coalesce(tally_j1_tbl.c2_score, 0)) + sum(coalesce(tally_j2_tbl.c1_score, 0)) + sum(coalesce(tally_j2_tbl.c2_score, 0)) AS total,
RANK() OVER (
ORDER BY sum(coalesce(tally_j1_tbl.c1_score, 0)) + sum(coalesce(tally_j1_tbl.c2_score, 0)) + sum(coalesce(tally_j2_tbl.c1_score, 0)) + sum(coalesce(tally_j2_tbl.c2_score, 0))
) as pos
FROM
contestant_tbl
LEFT JOIN tally_j1_tbl ON contestant_tbl.contestant_num = tally_j1_tbl.contestant_num
LEFT JOIN tally_j2_tbl ON contestant_tbl.contestant_num = tally_j2_tbl.contestant_num
GROUP BY
contestant_tbl.contestant_num
ORDER BY
sum(coalesce(tally_j1_tbl.c1_score, 0)) + sum(coalesce(tally_j1_tbl.c2_score, 0)) + sum(coalesce(tally_j2_tbl.c1_score, 0)) + sum(coalesce(tally_j2_tbl.c2_score, 0))

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 improve/simplify a query with a lot of subquerys?

I have a sql query that sum and counts some registers from my db, the problem is that I'm using a lot of subquerys and all of them have the same condition, I need to find a better solution because this is causing slowness in my system.
I tried to use a simple left join but mysql returned a single row and I want that counts and sum every register on the table dbgeneralesImportacion.
I have something like this:
SELECT dbgeneralesImportacion.id,
sapito.dbgeneralesImportacion.documentosCompletos AS 'documentosCompletos',
(SELECT COUNT(c.id)
FROM sapito.dbcontenedores c
WHERE c.operacion = dbgeneralesImportacion.id ) AS 'ContadorContenedores',
(SELECT SUM(IF(c.estatus = 1, 1, 0))
FROM sapito.dbcontenedores c
WHERE c.operacion = dbgeneralesImportacion.id ) AS 'ContadorDespachos',
(SELECT SUM(IF(c.estatus = 2, 1, 0))
FROM sapito.dbcontenedores c
WHERE c.operacion = dbgeneralesImportacion.id ) AS 'ContadorCompletado',
(SELECT SUM(IF(c.desconsolidacion = 1, 1, 0))
FROM sapito.dbcontenedores c
WHERE c.operacion = dbgeneralesImportacion.id ) AS 'DesconsolidacionPuerto',
(SELECT SUM(c.bultos) FROM sapito.dbcontenedores c WHERE c.operacion = dbgeneralesImportacion.id) AS 'bultos'
FROM dbgeneralesImportacion
And my idea was to do this but counts all register and return a single row:
SELECT dbgeneralesImportacion.id AS 'id',
COUNT(c.id) AS 'ContadorContenedores',
SUM(IF(c.estatus = 1, 1, 0)) AS 'ContadorDespachos',
SUM(IF(c.estatus = 2, 1, 0)) AS 'ContadorCompletado',
SUM(IF(c.desconsolidacion = 1, 1, 0)) AS 'DesconsolidacionPuerto',
SUM(c.bultos) AS 'bultos'
FROM dbgeneralesImportacion
LEFT JOIN dbcontenedores c ON c.operacion = dbgeneralesImportacion.id
Thank you everyone
You could use a join a and group by
SELECT a.id
, a.documentosCompletos
, COUNT(c.id) ContadorContenedores
, SUM(IF(c.estatus = 1, 1, 0)) ContadorDespachos
, SUM(IF(c.estatus = 2, 1, 0)) ContadorCompletado
, SUM(IF(c.desconsolidacion = 1, 1, 0)) DesconsolidacionPuerto
, SUM(c.bultos) bultos
FROM dbgeneralesImportacion a
INNER JOIN sapito.dbcontenedores c ON c.operacion = a.id
GRUP BY a.id, a.documentosCompletos
Not positive, but couldn't you do something like this
SELECT dbgeneralesImportacion.id,
sapito.dbgeneralesImportacion.documentosCompletos AS 'documentosCompletos',
COUNT(c.id) AS 'ContadorContenedores',
SUM(IF(c.estatus = 1, 1, 0)) AS 'ContadorDespachos',
SUM(IF(c.estatus = 2, 1, 0)) AS 'ContadorCompletado',
SUM(IF(c.desconsolidacion = 1, 1, 0)) AS 'DesconsolidacionPuerto',
SUM(c.bultos) AS 'bultos'
FROM dbgeneralesImportacion, sapito.dbcontenedores c
WHERE c.operacion = dbgeneralesImportacion.id
GROUP BY dbgeneralesImportacion.id
You need a GROUP BY, but you can also simplify the query:
SELECT gi.id AS id,
COUNT(c.id) AS ContadorContenedores,
SUM( c.estatus = 1 ) AS ContadorDespachos,
SUM( c.estatus = 2 ) AS ContadorCompletado,
SUM( c.desconsolidacion = 1 ) AS DesconsolidacionPuerto,
SUM(c.bultos) AS bultos
FROM dbgeneralesImportacion LEFT JOIN
dbcontenedores c
ON c.operacion = gi.id
GROUP BY gi.id;
MySQL treats boolean values as numbers in a numeric context, with true being 1 and false being 0. This makes it easy to count up matching values.
Also, only use single quotes for string and date constants. Using them for column aliases can lead to hard-to-debug problems.

SQL - Group and count duplicates row

I have no idea how to group and count duplicates row on mysql
below is the result that I got from my query
ssn + checktime + nama
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
'196702031989031001' + '2018-08-03 07:33:02' + 'FAJAR PERMADI'
'196810021993031001' + '2018-08-01 07:33:25' + 'ANDRI ANGGORO, SH'
'196911052000031001' + '2018-08-03 07:47:22' + 'SEMI TEDDY RORY, SS'
'196912221994032001' + '2018-08-01 08:03:59' + 'AI SALATUN'
'196912221994032001' + '2018-08-02 09:34:11' + 'AI SALATUN'
'196912221994032001' + '2018-08-03 07:33:18' + 'AI SALATUN'
'197012051993031001' + '2018-08-01 07:58:47' + 'AHMAD SODIKIN, SH'
'197012192001121001' + '2018-08-01 09:54:21' + 'JUARA PAHALA MARBUN, ST'
'197012192001121001' + '2018-08-02 09:39:41' + 'JUARA PAHALA MARBUN, ST'
and below is my query
SELECT a.ssn, a.checktime, b.nama
FROM hki_kepegawaian.fo_absensi a
left join hki_kepegawaian.fo_pegawai b on a.ssn = b.nip
where (substring(cast(checktime as DATE), 6, 2) = '08')
and (cast(a.checktime as TIME)) >= '07:30:00' and (cast(a.checktime as
TIME)) <= '10:00:00'
and (substring(golongan, 1, 2)) NOT IN ('IV')
group by ssn, cast(a.checktime as date)
and below is result that I expected
ssn + checktime + nama + total
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
'196702031989031001' + '2018-08-03 07:33:02' + 'FAJAR PERMADI' + 1
'196810021993031001' + '2018-08-01 07:33:25' + 'ANDRI ANGGORO, SH' + 1
'196911052000031001' + '2018-08-03 07:47:22' + 'SEMI TEDDY RORY, SS' + 1
'196912221994032001' + '2018-08-01 08:03:59' + 'AI SALATUN' + 3
'197012051993031001' + '2018-08-01 07:58:47' + 'AHMAD SODIKIN, SH' + 1
'197012192001121001' + '2018-08-01 09:54:21' + 'JUARA PAHALA MARBUN, ST' + 2
Your expected output implies that you want to report the record having the earliest check time for each ssn/nama group of records. For the count, it just looks like the total number of records in each group.
SELECT
a.ssn,
MIN(CAST(a.checktime AS date)) AS checktime,
b.nama,
COUNT(*) AS total
FROM hki_kepegawaian.fo_absensi a
LEFT JOIN hki_kepegawaian.fo_pegawai b
ON a.ssn = b.nip
WHERE
MONTH(checktime) = 8 AND
CAST(a.checktime AS TIME) BETWEEN '07:30:00' AND '10:00:00' AND
SUBSTRING(golongan, 1, 2)) <> 'IV'
GROUP BY
a.ssn, CAST(a.checktime AS date);
I agree with Tim that you seem to want to take the earliest time. This is accomplished with a group by in this case.
However, there are some other fixes to the query that I would suggest:
Do not use string operations on date/times.
Use meaningful table aliases that are abbreviations for the table.
Include all unaggregated columns in the GROUP BY.
Use LIKE where appropriate.
So, I would suggest:
SELECT a.ssn, a.checktime, p.nama
FROM hki_kepegawaian.fo_absensi a LEFT JOIN
hki_kepegawaian.fo_pegawai b
ON a.ssn = p.nip
WHERE MONTH(checktime) = 8 AND
CAST(a.checktime as TIME) >= '07:30:00' AND
CAST(a.checktime as TIME)) <= '10:00:00' AND
golongan NOT LIKE 'IV%'
GROUP BY a.ssn, p.nama;
Look into count() function.
I can't check whether it works, but try the following query:
SELECT a.ssn, a.checktime, b.nama, count(*) as total
FROM hki_kepegawaian.fo_absensi a
left join hki_kepegawaian.fo_pegawai b on a.ssn = b.nip
where (substring(cast(checktime as DATE), 6, 2) = '08')
and (cast(a.checktime as TIME)) >= '07:30:00' and (cast(a.checktime as
TIME)) <= '10:00:00'
and (substring(golongan, 1, 2)) NOT IN ('IV')
group by ssn, nama
Having total>=1

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.

Multiple nested if statment in MySQL query

I'm trying the query below and MySQL gave me this error: Invalid use of group function
SELECT C.`some_name`,
SUM(IF(A.`med_type` = 1, SUM(A.`med_qty`), 0)) AS total,
SUM(IF(A.`is_rejected` = 4, 1 , 0)) AS approved,
SUM(IF(A.`is_rejected` = 2, 1 , 0)) AS qeue,
SUM(IF(A.`is_rejected` = 3, 1 , 0)) AS rejected,
SUM(IF(A.`is_rejected` = 1, 1 , 0)) AS fresh
FROM `ne_media` A
INNER JOIN `ne_member` B ON A.`mem_id` = B.`mem_id`
INNER JOIN `ne_some` C ON B.`some_id` = C.`some_id`
GROUP BY C.`some_id`;
I want to sum med_qty just if med_type = 1.
How do I do it?
Use:
SUM(CASE WHEN (A.`med_type` = 1) THEN A.`med_qty` ELSE 0 END)) AS total,
or:
SUM(IF(A.`med_type` = 1, A.`med_qty`, 0)) AS total,
You can't do aggregates on aggregates like you tried to in the original.