My scenario is... I have 2 type of judges who will give different set of points to members (eg. Judge Type A(55%) and Judge Type B(45%)) Both set of points will sum separately and averaged and then will sum together (which is 100% in total of 2 judges' points). I want to union both results into expected output below.
Table Member
-----------------------------
ID | Name
1 | John
2 | Doe
-----------------------------
Table Judge
-----------------------------
ID | Type | Name
1 | 1 | Judge A
2 | 1 | Judge B
3 | 2 | Judge C
4 | 1 | Judge D
-----------------------------
Table Point
-----------------------------
ID | FK | Judge | Type | Point
1 | 1 | 1 | 1 | 10
2 | 1 | 1 | 2 | 15
3 | 1 | 1 | 3 | 15
4 | 2 | 2 | 1 | 8
5 | 2 | 2 | 2 | 6
6 | 2 | 2 | 3 | 5
7 | 2 | 3 | 4 | 3
8 | 2 | 3 | 5 | 2
9 | 2 | 3 | 6 | 1
10 | 2 | 4 | 1 | 3
11 | 2 | 4 | 2 | 6
12 | 2 | 4 | 3 | 12
-----------------------------
Output Total Points
-----------------------------
ID | Name | Type1 | Type2 | Type3 | Total1 | CountJudge1 | Type4 | Type5 | Type6 | Total2 | CountJudge2
1 | John | 10 | 15 | 15 | 40 | 1 | 0 | 0 | 0 | 0 | 0
2 | Doe | 11 | 12 | 17 | 40 | 2 | 3 | 2 | 1 | 6 | 1
-----------------------------
Expected Output
-----------------------------
ID | Name | Type1 | Type2 | Type3 | Total1 | CountJudge1 | Type4 | Type5 | Type6 | Total2 | CountJudge2 | TotalPoint
1 | John | 10 | 15 | 15 | 40 | 1 | 0 | 0 | 0 | 0 | 0 | 40
2 | Doe | 5.5 | 6 | 8.5 | 20 | 2 | 3 | 2 | 1 | 6 | 1 | 26
-----------------------------
The sql (Output Total Points) that I could do at this moment which is still wrong is below and I can't figure out how to average all types of point and total points.
SELECT m.Name,
COUNT( CASE WHEN j.Type=1 THEN j.ID ELSE 0 END ) AS Judge1,
SUM( CASE WHEN p.Type=1 THEN p.Point ELSE 0 END ) AS Type1,
SUM( CASE WHEN p.Type=2 THEN p.Point ELSE 0 END ) AS Type2,
SUM( CASE WHEN p.Type=3 THEN p.Point ELSE 0 END ) AS Type3,
SUM( p.Score ) AS Total1,
COUNT( CASE WHEN j.Type=2 THEN j.ID ELSE 0 END ) AS Judge2,
SUM( CASE WHEN p.Type=4 THEN p.Point ELSE 0 END ) AS Type4,
SUM( CASE WHEN p.Type=5 THEN p.Point ELSE 0 END ) AS Type5,
SUM( CASE WHEN p.Type=6 THEN p.Point ELSE 0 END ) AS Type6,
SUM( p.Score ) AS Total2
FROM table_point AS p
LEFT JOIN table_member AS m ON ( m.ID = p.FK)
LEFT JOIN table_judge AS j ON ( j.ID = p.Judge )
GROUP BY m.ID
* UPDATE 1 *
I figured out the statement for expected result. However, as data grows bigger, my statement get slower. (250 members, 13 judges, 9750 scores (3 scores per judge per student) takes bout +-6 seconds). When I doubled members and scores, the execution time also doubled. Any idea to optimize this query?
SELECT MemberID, MemberName,
Judge1, Score1, Score2, Score3,
Judge2, Score4, Score5, Score6,
(((Score1 + Score2 + Score3) / (Judge1 / 3)) + ((Score4 + Score5 + Score6) / (Judge2 / 3))) AS TotalScore
FROM
(
SELECT m.ID AS MemberID, m.Name AS MemberName,
COUNT(j1.ID) AS Judge1,
SUM(CASE WHEN p.TypeID=1 THEN p.Point ELSE 0 END) AS Score1,
SUM(CASE WHEN p.TypeID=2 THEN p.Point ELSE 0 END) AS Score2,
SUM(CASE WHEN p.TypeID=3 THEN p.Point ELSE 0 END) AS Score3,
COUNT(j2.ID) AS Judge2,
SUM(CASE WHEN p.TypeID=4 THEN p.Point ELSE 0 END) AS Score4,
SUM(CASE WHEN p.TypeID=5 THEN p.Point ELSE 0 END) AS Score5,
SUM(CASE WHEN p.TypeID=6 THEN p.Point ELSE 0 END) AS Score6
FROM table_point AS p
LEFT JOIN table_member AS m ON ( m.ID = p.FK)
LEFT JOIN table_judge AS j1 ON ( j1.ID = p.Judge AND j1.Type=1 )
LEFT JOIN table_judge AS j2 ON ( j2.ID = p.Judge AND j2.Type=2 )
GROUP BY m.ID
) as tbl1
ORDER BY TotalScore DESC
Related
I have a table 'A' that looks something like:
_______________________________________________________________
|query_id | query | response |user_response_count |
|---------------------------------------------------------------
| 1 | acne | BothBad | 2 |
| 1 | acne | BothGood | 1 |
| 2 | asthma | BothBad | 1 |
| 2 | asthma | product 1 | 1 |
| 2 | asthma | BothGood | 1 |
| 3 | bell palsy | product 2 | 2 |
| 3 | bell palsy | BothGood | 1 |
---------------------------------------------------------------
I want to write a query to get something that looks like:
__________________________________________________________________________________
| query_id | query | BothGood | BothBad | Product 1 | Product 2 |
-----------------------------------------------------------------------------------
| 1 | acne | 1 | 2 | 0 | 0 |
| 2 | asthma | 1 | 1 | 1 | 0 |
| 3 | bell palsy| 1 | 0 | 0 | 2 |
-----------------------------------------------------------------------------------
That "user_response_count" column actually says, 2 users selected "BothBad" option for "acne" query.
I know, by using max, I can change my rows to the column, but here it would be difficult to the max. Any Thoughts?
Conditional aggregation:
select query_id, query,
sum(case when response = 'BothGood' then cnt else 0 end) as BothGood,
sum(case when response = 'BothBad' then cnt else 0 end) as BothBad,
sum(case when response = 'product 1' then cnt else 0 end) as product1,
sum(case when response = 'product 2' then cnt else 0 end) as product2
from a
group by query_id, query;
You can use a conditional aggregation as
select query_id, query,
max( coalesce(case when response = 'BothGood' then user_response_count end,0) )
as BothGood,
max( coalesce(case when response = 'BothBad' then user_response_count end,0) )
as BothBad,
max( coalesce(case when response = 'product 1' then user_response_count end,0) )
as Product_1,
max( coalesce(case when response = 'product 2' then user_response_count end,0) )
as Product_2
from tableA
group by query_id, query
Demo
I have the following table. I would like to add 2 new columns with a select query that will show the total based on the flag type.
Table:
tt | company | count | flag
--------------------------------------------
123 | adeco | 5 | 1
123 | mic | 4 | 2
333 | manpower | 88 | 2
444 | linar | 2 | 2
555 | dlank | 3 | 1
Desired:
tt | company | total | flag | total_flag1 | total_flag2
-------------------------------------------------------------------
123 | adeco | 5 | 1 | 5 | 0
123 | mic | 4 | 2 | 0 | 4
333 | manpower | 88 | 2 | 0 | 88
444 | linar | 2 | 2 | 0 | 2
555 | dlank | 3 | 1 | 3 | 0
By your desired result, you should use case when or if syntax to to this:
select
yourtable.*,
case when flag = 1 then `count` else 0 end as total_flag1,
case when flag = 2 then `count` else 0 end as total_flag2
from yourtable
Or
select
yourtable.*,
if(flag = 1, `count`, 0) as total_flag1,
if(flag = 2, `count`, 0) as total_flag2
from yourtable
I think you can do what you want using correlated subqueries or join:
select t.*, tsum.total_flag1, tsum.total_flag2
from t join
(select t.tt,
sum(case when flag = 1 then total else 0 end) as total_flag1,
sum(case when flag = 2 then total else 0 end) as total_flag2
from t
group by t.tt
) tsum
on t.tt = tsum.tt;
I need some help with this SQL running total. I've tried some of the suggestions but haven't got it to work 100% and my totals are not in order.
The query shows number of stones and number of carats produced each day, first for stones over 5 carats, then for stones under 5 carats, so after first column which is the date, those 4 columns appear.
Then the next two columns simply add the stones together and the carats together for daily totals.
After that I would like to add two columns which create running totals of stones and carats.
Any help would be appreciated. Thank you!
select
`dbo_List_Dates`.`Full_Date` AS `Full_Date`,
if(isnull(`qry_Register_Over5ct`.`StonesO5`),
0,`qry_Register_Over5ct`.`StonesO5`) AS `StonesO5`,
if(isnull(`qry_Register_Over5ct`.`CaratsO5`),
0,format(`qry_Register_Over5ct`.`CaratsO5`,3)) AS `CaratsO5`,
if(isnull(`qry_Register_Under5ct`.`StonesU5`),
0,`qry_Register_Under5ct`.`StonesU5`) AS `StonesU5`,
if(isnull(`qry_Register_Under5ct`.`CaratsU5`),
0,format(`qry_Register_Under5ct`.`CaratsU5`,3)) AS `CaratsU5`,
(if(isnull(`qry_Register_Over5ct`.`StonesO5`),
0,`qry_Register_Over5ct`.`StonesO5`) + if(isnull(`qry_Register_Under5ct`.`StonesU5`),
0,`qry_Register_Under5ct`.`StonesU5`)) AS `Stones`,
format((if(isnull(`qry_Register_Over5ct`.`CaratsO5`),
0,`qry_Register_Over5ct`.`CaratsO5`) + if(isnull(`qry_Register_Under5ct`.`CaratsU5`),
0,`qry_Register_Under5ct`.`CaratsU5`)),3) AS `Carats`,
date_format(`dbo_List_Dates`.`Full_Date`,'%Y-%m') AS `Date_Filter`
from
(
(`dbo_List_Dates`
left join `qry_Register_Over5ct`
on((`dbo_List_Dates`.`Full_Date`=qry_Register_Over5ct`.`Shift_Date`))
)
left join `qry_Register_Under5ct`
on((`dbo_List_Dates`.`Full_Date`=`qry_Register_Under5ct`.`Shift_Date`))
)
where
(date_format(`dbo_List_Dates`.`Full_Date`,'%Y-%m') = date_format(now(),'%Y-%m'))
order by
`dbo_List_Dates`.`Full_Date`
limit 0,31
Running totals in mysql require the use of variables.
For example given
create table register (id int, dt date, carats int);
insert into register values
(1,'2016-11-01',10),(2,'2016-11-01',10),(3,'2016-11-01',1),
(4,'2016-11-02',1),
(5,'2016-11-03',10),
(6,'2016-11-05',10),(7,'2016-11-05',1);
and a dates table like this
+------------+
| dte |
+------------+
| 2016-11-01 |
| 2016-11-02 |
| 2016-11-03 |
| 2016-11-04 |
| 2016-11-05 |
+------------+
select s.* ,#RunningTotal:=#RunningTotal + s.LT5_GE5 RunningTotal
from
(
select d.dte,
sum(case when r.dt is not null and r.carats >= 5 then 1 else 0 end) GE5,
sum(case when r.dt is not null and r.carats < 5 then 1 else 0 end) LT5,
sum(case when r.dt is not null and r.carats >= 5 then 1 else 0 end) +
sum(case when r.dt is not null and r.carats < 5 then 1 else 0 end) LT5_GE5
from dates d
left join register r on r.dt = d.dte
where dte between '2016-11-01' and '2016-11-05'
group by dte
) s ,(select #RunningTotal:=0) rt
Results
+------------+------+------+---------+--------------+
| dte | GE5 | LT5 | LT5_GE5 | RunningTotal |
+------------+------+------+---------+--------------+
| 2016-11-01 | 2 | 1 | 3 | 3 |
| 2016-11-02 | 0 | 1 | 1 | 4 |
| 2016-11-03 | 1 | 0 | 1 | 5 |
| 2016-11-04 | 0 | 0 | 0 | 5 |
| 2016-11-05 | 1 | 1 | 2 | 7 |
+------------+------+------+---------+--------------+
And if you want column totals you could include a rollup in the group by
select s.* ,
cast(if(dte is null,#RunningTotal,#RunningTotal:=#RunningTotal + s.LT5_GE5) as int) RunningTotal
from
(
select d.dte,
sum(case when r.dt is not null and r.carats >= 5 then 1 else 0 end) GE5,
sum(case when r.dt is not null and r.carats < 5 then 1 else 0 end) LT5,
sum(case when r.dt is not null and r.carats >= 5 then 1 else 0 end) +
sum(case when r.dt is not null and r.carats < 5 then 1 else 0 end) LT5_GE5
from dates d
left join register r on r.dt = d.dte
where dte between '2016-11-01' and '2016-11-05'
group by dte with rollup
) s ,(select #RunningTotal:=0) rt
Result
+------------+------+------+---------+--------------+
| dte | GE5 | LT5 | LT5_GE5 | RunningTotal |
+------------+------+------+---------+--------------+
| 2016-11-01 | 2 | 1 | 3 | 3 |
| 2016-11-02 | 0 | 1 | 1 | 4 |
| 2016-11-03 | 1 | 0 | 1 | 5 |
| 2016-11-04 | 0 | 0 | 0 | 5 |
| 2016-11-05 | 1 | 1 | 2 | 7 |
| NULL | 4 | 3 | 7 | 7 |
+------------+------+------+---------+--------------+
6 rows in set (0.02 sec)
I have 4 tables as a bellow
table : user
id_tkn | nm_user |
-----------------------------------------
1 | belva |
2 | nanda |
3 | maya |
-----------------------------------------
table : maintenance
id_mntnc|id_tkn | sts | date |
-----------------------------------------------------------------
1 | 2 | 1 |2016-03-03 |
2 | 2 | 2 |2016-03-03 |
3 | 1 | 1 |2016-03-03 |
4 | 2 | 0 |2016-03-03 |
5 | 2 | 1 |2016-03-03 |
-----------------------------------------------------------------
table : Installasi
id_istlsi|id_tkn| sts | date |
-----------------------------------------------------------------
1 | 2 | 1 |2016-03-03 |
2 | 1 | 1 |2016-03-03 |
3 | 1 | 1 |2016-03-03 |
4 | 2 | 1 |2016-03-03 |
5 | 3 | 1 |2016-03-03 |
-----------------------------------------------------------------
table : visit
id_vst |id_tkn | sts | date |
-----------------------------------------------------------------
1 | 2 | 1 |2016-03-03 |
2 | 2 | 0 |2016-03-03 |
3 | 1 | 1 |2016-03-03 |
-----------------------------------------------------------------
information about 'sts' column
0 --> Pending
1 --> Success
2 --> Fail.
from the table above,I want to add up by status(sts) where id_tkn = 2,the result like table below,how to generate SQL command to produce the table below ?
id_tkn | nm_usr | maintenance_suc | maintenance_fail | installasi_suc| installasi_fail | visit_suc| visit_fail
-----------------------------------------------------------------------------------------------------------------------
2 | nanda | 2 | 1 | 2 | 0 | 1 | 0
This should work right, but probably need to be optimized:
select
u.id_tkn,
u.nm_user,
sum ( case when stat.sts = 1 and stat.typ = 'm' then 1 else 0 end ) as maintenance_suc,
sum ( case when stat.sts = 2 and stat.typ = 'm' then 1 else 0 end ) as maintenance_fail,
sum ( case when stat.sts = 1 and stat.typ = 'i' then 1 else 0 end ) as installasi_suc,
sum ( case when stat.sts = 2 and stat.typ = 'i' then 1 else 0 end ) as installasi_fail,
sum ( case when stat.sts = 1 and stat.typ = 'v' then 1 else 0 end ) as visit_suc,
sum ( case when stat.sts = 2 and stat.typ = 'v' then 1 else 0 end ) as visit_fail
from
user u
left join
(
select sts, 'm', id_tkn
from
maintenance
union all
select sts, 'i', id_tkn
from
Installasi
union all
select sts, 'v', id_tkn
from
visit
) stat on u.id_tkn = stat.id_tkn
where u.id_tkn = 2
group by u.id_tkn, u.nm_user
I have data where each row represents one sentence in full review. Each row has a score (-1 to 1).
From that view I currently make 3 views where each has different group by, either by day, month or week and which aggregates average score for a review and
counts how many of them are positive and how many negative.
For example daily query from view:
SELECT
`review_score_view`.`review_date` AS `review_date`,
COUNT(`review_score_view`.`review_id`) AS `review_count`,
(AVG(`review_score_view`.`score`) * 100) AS `average_score`,
SUM((CASE
WHEN (`review_score_view`.`score` >= 0) THEN 1
ELSE 0
END)) AS `positive_count`,
SUM((CASE
WHEN (`review_score_view`.`score` < 0) THEN 1
ELSE 0
END)) AS `negative_count`
FROM
`review_score_view`
GROUP BY `review_score_view`.`review_date`
And I get result like this:
| id | review_date | review_count | average_score | positive_count | negative_count |
|-----|--------------|--------------|-----------------|----------------|----------------|
| 521 | 2015-01-01 | 4 | -25.0000 | 2 | 2 |
| 519 | 2015-01-07 | 1 | -100.0000 | 0 | 1 |
| 518 | 2015-01-25 | 1 | 100.0000 | 1 | 0 |
| 516 | 2015-03-09 | 7 | 57.1429 | 6 | 1 |
| 515 | 2015-04-26 | 2 | -50.0000 | 1 | 1 |
| 224 | 2015-06-01 | 68 | -23.5294 | 40 | 28 |
| 222 | 2015-06-02 | 26 | -100.0000 | 1 | 25 |
| 221 | 2015-06-03 | 41 | -36.5854 | 19 | 22 |
| 220 | 2015-06-04 | 6 | -50.0000 | 2 | 4 |
Question: How I can make another query from these view results based on average score. For each result (score categories), based on group by, either monthly, weekly or daily, I'd like to get a sum of these 5 results. Seems like an easy thing but I can't get my head around it.
SUM((CASE
WHEN (average_score >= 75) THEN 1
ELSE 0
END)) AS very_positive,
SUM((CASE
WHEN (average_score between 4 and 74) THEN 1
ELSE 0
END)) AS positive,
SUM((CASE
WHEN (average_score between -5 and 5) THEN 1
ELSE 0
END)) AS neutral,
SUM((CASE
WHEN (average_score between -4 and -74) THEN 1
ELSE 0
END)) AS negative,
SUM((CASE
WHEN (average_score <= -75) THEN 1
ELSE 0
END)) AS very_negative
Finally I would just plot the data. Quick example made in Excel:
Thanks in advance.
Hmmm. It looks like you want the results in rows, not columns. This suggests group by:
SELECT (CASE WHEN average_score >= 75 THEN 'VeryPositive'
WHEN average_score >= 4 THEN 'Positive'
WHEN average_score >= -5 THEN 'Neutral'
WHEN average_score >= -74 THEN 'Negative'
ELSE 'VeryNegative'
END) as ScoreGroup,
COUNT(*) as cnt
FROM dailyview v
GROUP BY ScoreGroup
ORDER BY ScoreGroup;
Note: The case returns the first expression that matches, so the between is unnecessary.