SQL, sum inside of case condition - mysql

I'm trying to learn sql query and i want to solve the following problem.
Assume the table as follow:
id
schoolname
totalA
totalB
grade
1
school A
5
5
1
2
school A
5
5
2
3
school B
5
5
1
4
school B
5
5
2
Select schoolname
SUM(CASE WHEN (grade='1' ) THEN totalA ELSE 0 END) AS t1A,
SUM(CASE WHEN (grade='1' ) THEN totalB ELSE 0 END) AS t1B,
SUM(CASE WHEN (grade='2' ) THEN totalA ELSE 0 END) AS t2A,
SUM(CASE WHEN (grade='2' ) THEN totalB ELSE 0 END) AS t2B,
I would like to know if it is possible to add both totalA and B in one case condition.
I tried
Select schoolname
CASE WHEN (grade='1' ) THEN SUM(totalA+totalB) ELSE 0 END AS Grade 1,
CASE WHEN (grade='2' ) THEN SUM(totalA+totalB) ELSE 0 END AS Grade 2,
From school
Group By schoolname
But it give me error.
I want to achieve the following:
schoolname
grade 1
grade 2
School A
10
10
School B
10
10

Yes it is possible by group by query of MySQL in the same table.
For that you need to use this type of query:
SELECT schoolname,
SUM(CASE WHEN (grade = 1) THEN totalA + totalB ELSE 0 END) AS grade_1,
SUM(CASE WHEN (grade = 2) THEN totalA + totalB ELSE 0 END) AS grade_2
FROM school
GROUP BY schoolname

Related

MySQL- Count total records based on different values of same column

I have a table as follows
table_user
id name status flag country
====================================================================================================
1 AB 1 0 US
2 BC 1 0 UK
3 CD 0 0 IN
4 DE 3 0 BR
5 EF 3 0 UK
6 FG 2 0 IN
7 GH 4 0 IN
I want to count the no. of records where
status = 1 as totalactiverecords,
status = 0 as totalinactiverecords,
status = 3 as totalrecentactiverecords,
status = 2 as totalemailnotverifiedrecords,
status = 4 as totalemailverifiedrecords,
, and country is UK, all in a single SELECT statement.
Is there any specific way to do it?
I have thought of something like
SELECT COUNT(*) as totalactiverecords WHERE status=1
COUNT(*) as totalinactiverecordsWHERE status=0,
COUNT(*) as totalemailnotverifiedrecords WHERE status=2,
COUNT(*) as totalrecentactiverecords WHERE status=3,
COUNT(*) as totalemailverifiedrecords WHERE status=4
FROM table_user where country=IN
,but that does not seem to work.
You can try this query:
SELECT count(case status when '1' then 1 else null end) as totalactiverecords,
count(case status when '0' then 1 else null end) as totalinactiverecords,
count(case status when '2' then 1 else null end) as totalemailnotverifiedrecords,
count(case status when '3' then 1 else null end) as totalrecentactiverecords,
count(case status when '4' then 1 else null end) as totalemailverifiedrecords
FROM table_user where country='IN'
I usually use CASE WHEN in this kind of problem:
SELECT sum(case when status = 1 then 1 end) as totalactiverecords,
COUNT sum(case when status = 0 then 1 end) as totalinactiverecords,
COUNT sum(case when status = 2 then 1 end) as totalemailnotverifiedrecord,
COUNT sum(case when status = 3 then 1 end) as totalrecentactiverecords,
COUNT sum(case when status = 4 then 1 end) as totalemailverifiedrecords
FROM table_user where country=IN

Distinct Count Query

I have a table below:
Item Status1 Status2
-----------------------------
A Good NULL
A Good NULL
A Good NULL
A Bad Good
B Bad Good
B Good NULL
C Good NULL
C Good NULL
C Good NULL
D Bad Good
Now, I'm thinking off writing a query which gives me the result below:
Item Good Bad
-----------------------------
A 4 1
B 2 1
C 3 0
D 1 1
Distinct in the Item column and the count of Good and Bad for each Item where NULL is not counted.
The column name can be of anything (I just kept it as Good and Bad in my second table).
Any suggestions/ideas on how to achieve my desired results?
Use UNION ALL & do aggregation :
select item, sum(status = 'good'), sum(status = 'bad')
from (select item, status1 as status
from table t
union all
select item, status2
from table t
) t
group by item;
You can use union all and conditional aggregation
select item, count(case when status1='good' then 1 end) as good,
count(case when status1='bad' then 1 end) as bad
from
(
select item , status1 from tablename
union all
select item , status2 from tablename
)A group by item
use union and case when
select Item, sum(case when status = 'good' then 1 else 0 end) as good,
sum ( case when status = 'bad' then 1 else 0 end) as bad
from (select Item, Status1 as status
from table_name
union all
select Item, Status2
from table_name
) t
group by Item;
There's no need for UNION, simply apply some logic.
select Item
,sum(case when Status1 = 'Good' then 1 else 0 end +
case when Status2 = 'Good' then 1 else 0 end) as good
,sum(case when Status1 = 'Bad' then 1 else 0 end +
case when Status2 = 'Bad' then 1 else 0 end) as bad
from tab
group by Item
or
select Item
,count(case when Status1 = 'Good' then 1 end) +
count(case when Status2 = 'Good' then 1 end) as good
,count(case when Status1 = 'Bad' then 1 end) +
count(case when Status2 = 'Bad' then 1 end) as good
from tab
group by Item
You can use sub-query and then apply sum function in outer query
select distinct(item) as item, sum(S1G+S2G) as Good,sum(S1B+S2B) as Bad from ( select item, CASE WHEN status1 ='Good' THEN 1 ELSE 0 END as S1G, CASE WHEN status2 ='Good' THEN 1 ELSE 0 END as S2G, CASE WHEN status2 ='Bad' THEN 1 ELSE 0 END as S2B, CASE WHEN status1 ='Bad' THEN 1 ELSE 0 END as S1B from t1 ) as b group by item
Here is demo

SUM CASE adding from joined table instead main table

I have a query that retrieves from a customer:
sum of time expent on his tickets (every ticket can have 1 or more interventions)
average resolution time
category of each ticket
The query:
SELECT SUM(f.duree) as total_time, SUM(timestampdiff(second, t.datec, t.date_close))/COUNT(distinct t.rowid) as average_resolution, COUNT(distinct t.rowid) as tickets,
SUM( CASE t.category_code WHEN 'WITHOUT_MAINTENANCE' THEN 1 ELSE 0 END) as sin_mantenimiento,
SUM( CASE t.category_code WHEN 'WITH_MAINTENANCE' THEN 1 ELSE 0 END) as con_mantenimiento,
SUM( CASE t.category_code WHEN 'WITH_BILLABLE_MAINTENANCE' THEN 1 ELSE 0 END) as con_mantenimiento_facturable,
SUM( CASE t.category_code WHEN 'NO_BILLABLE_COASER_WARRANTY' THEN 1 ELSE 0 END) as no_facturable_garantia_coaser,
SUM( CASE t.category_code WHEN 'OFERTADO' THEN 1 ELSE 0 END) as ofertado
FROM llx_ticketsup as t
JOIN llx_element_element as ee on ee.fk_source = t.rowid
JOIN llx_fichinter as f on f.rowid = ee.fk_target
WHERE t.fk_soc = 47 AND t.fk_statut = 8
where
llx_ticketsup is main tickets table
llx_fichinter is table where interventions from tickets are stored
llx_element_element is table between tickets and interventions
My problem is, if one ticket has more than 1 intervention, on sum of category types to know how many are from this category and how many from the other, it sums interventions instead tickets. For example, if query returns 2 tickets and they have a total of 6 interventions, it returns 6 tickets of category WITHOUT_MAINTENANCE, instead 2 tickets of category WITHOUT_MAINTENANCE.
Whats wrong? Thanks.
Nothings 'wrong' that's expected behaviour try using a sub query to get the duration. Something like
SELECT (select sum(f.duree) from llx_fichinter as f on f.rowid = ee.fk_target) as total_time, SUM(timestampdiff(second, t.datec, t.date_close))/COUNT(distinct t.rowid) as average_resolution, COUNT(distinct t.rowid) as tickets,
SUM( CASE t.category_code WHEN 'WITHOUT_MAINTENANCE' THEN 1 ELSE 0 END) as sin_mantenimiento,
SUM( CASE t.category_code WHEN 'WITH_MAINTENANCE' THEN 1 ELSE 0 END) as con_mantenimiento,
SUM( CASE t.category_code WHEN 'WITH_BILLABLE_MAINTENANCE' THEN 1 ELSE 0 END) as con_mantenimiento_facturable,
SUM( CASE t.category_code WHEN 'NO_BILLABLE_COASER_WARRANTY' THEN 1 ELSE 0 END) as no_facturable_garantia_coaser,
SUM( CASE t.category_code WHEN 'OFERTADO' THEN 1 ELSE 0 END) as ofertado
FROM llx_ticketsup as t
JOIN llx_element_element as ee on ee.fk_source = t.rowid
WHERE t.fk_soc = 47 AND t.fk_statut = 8
If that doesn't work add sample data and expected result to the question as text so we can play with it.

how to select and group mysql data based on the following table

how can I achieve the desired result in mysql if my table looks like this.
result|year
1 |2011
2 |2011
1 |2011
0 |2011
1 |2012
2 |2012
1 = Won, 2 = lost, 0 = draw
Every year can have multiple values like this. Not sure how I can get the desired result like below.
year won lost draw totalPlayed
2011 2 1 1 3
2012 1 1 0 2
I have tried the following query but does not get the desired result
select year,
league_types.league_name,
sum(if(result = 1,1,0)) as won,
sum(if(result = 0,1,0)) as draw,
sum(if(result = 4,1,0)) as noResult,
sum(if(result = 2,1,0)) as lost,
sum(if(result = 3,1,0)) as tied,
sum(if(result > 0 and result < 4,1,0)) as played
from match_score_card
inner join fixtures on match_score_card.match_id = fixtures.match_id
inner join league_types on fixtures.league_id = league_types.league_id
where
team_id = 1 group by year order by year desc
Here is the SQL Fiddle that demonstrates the following query:
SELECT m.year,
SUM(CASE WHEN m.result = 1 THEN 1 ELSE 0 END) AS 'Won',
SUM(CASE WHEN m.result = 2 THEN 1 ELSE 0 END) AS 'Lost',
SUM(CASE WHEN m.result = 0 THEN 1 ELSE 0 END) AS 'Draw',
COUNT(*) AS 'TotalPlayed'
FROM MyTable AS m
GROUP BY m.year
I'm not familiar with that IF function in mySQL, but this standard SQL should work:
select year
, league_types.league_name
, sum(CASE WHEN result = 1 THEN 1 ELSE 0 END) as won
, sum(CASE WHEN result = 2 THEN 1 ELSE 0 END) as lost
, sum(CASE WHEN result = 3 THEN 1 ELSE 0 END) as draw
, sum(CASE WHEN result = 4 THEN 1 ELSE 0 END) as noResult
, sum(CASE WHEN result = 1
or result = 2 THEN 1 ELSE 0 END) as played
from match_score_card
inner join fixtures
on match_score_card.match_id = fixtures.match_id
inner join league_types
on fixtures.league_id = league_types.league_id
where team_id = 1
group by year, league_types.league_name
order by year desc, league_types.league_name
I'm guessing that you only want to count wins and losses as "played".

Multiple rows into one field on GROUPED results Mysql

I have a query results like this.
status count
-----------------
OTHER 5
ATTENDED 74
I want result like this:
OTHERS ATTENDED
5 74
Note this is already a grouped result. So I am thinking, Group_Concat might not work.
Query:
SELECT CASE Rstat WHEN 1 THEN 'ATTENDED'
WHEN 2 THEN 'TENTATIVE'
WHEN 3 THEN 'REJECTED'
WHEN 4 THEN 'OUTSTANDING'
WHEN 6 THEN 'ACCEPTED' ELSE 'OTHER' END AS 'status',
COUNT(Rstat) AS 'count'
FROM `eStatus`
GROUP BY RSTAT
Any other ideas?
SELECT SUM(CASE WHEN Rstat = 1 THEN 1 ELSE 0 END) AS ATTENDED,
SUM(CASE WHEN Rstat = 2 THEN 1 ELSE 0 END) AS TENTATIVE,
SUM(CASE WHEN Rstat = 3 THEN 1 ELSE 0 END) AS REJECTED,
SUM(CASE WHEN Rstat = 4 THEN 1 ELSE 0 END) AS OUTSTANDING,
SUM(CASE WHEN Rstat = 6 THEN 1 ELSE 0 END) AS ACCEPTED,
SUM(CASE WHEN Rstat NOT IN (1,2,3,4,6) THEN 1 ELSE 0 END) AS OTHER
FROM eStatus