Calculating Total of the row and finding average using MySQL - mysql

I have two tables App and Store
Grouped : It is the count of application that is grouped ie HasGroup =1
NonGrouped : It is the count of application that is not grouped ie HasGroup = 0
Grouped (%) : It is the percentage of application that is grouped ie HasGroup =1
NonGrouped (%) : It is the percentage of application that is not grouped ie HasGroup = 0
AverageNonGrouped (%) : It is the average of grouped application ie (Invidual NonGrouped(%) / total NonGrouped(%))*100. example for ABC it is (75/ 165)*100 = 45.45, similarly for XYZ it is (50/ 165)*100 = 30.30. Here 165 is the sum of 75+50+40
My query is as given below
SELECT
AppName,
SUM( CASE HasGroup WHEN 1 THEN 1 ELSE 0 END ) AS Grouped,
SUM( CASE HasGroup WHEN 0 THEN 1 ELSE 0 END ) AS NonGrouped,
ROUND(((SUM( CASE HasGroup WHEN 1 THEN 1 ELSE 0 END ) /
(SUM( CASE HasGroup WHEN 0 THEN 1 ELSE 0 END ) +
SUM( CASE HasGroup WHEN 1 THEN 1 ELSE 0 END )))*100), 2) AS GroupedPercentage,
ROUND(((SUM( CASE HasGroup WHEN 0 THEN 1 ELSE 0 END ) /
(SUM( CASE HasGroup WHEN 0 THEN 1 ELSE 0 END ) +
SUM( CASE HasGroup WHEN 1 THEN 1 ELSE 0 END )))*100), 2) AS NonGroupedPercentage
FROM
Apps
INNER JOIN Store
ON (Apps.Store = Store.Store)
AND AppName !='' GROUP BY AppName
I am able to find the columns except AverageNonGrouped (%) since I don't know how to get total NonGrouped(%), Can anyone please help me on this

It's big query, but it does the job (i've tested on a dataset localy)
SELECT
AppName,
SUM( CASE HasGroup WHEN 1 THEN 1 ELSE 0 END ) AS Grouped,
SUM( CASE HasGroup WHEN 0 THEN 1 ELSE 0 END ) AS NonGrouped,
ROUND(((SUM( CASE HasGroup WHEN 1 THEN 1 ELSE 0 END ) /
(SUM( CASE HasGroup WHEN 0 THEN 1 ELSE 0 END ) +
SUM( CASE HasGroup WHEN 1 THEN 1 ELSE 0 END )))*100), 2) AS GroupedPercentage,
ROUND(((SUM( CASE HasGroup WHEN 0 THEN 1 ELSE 0 END ) /
(SUM( CASE HasGroup WHEN 0 THEN 1 ELSE 0 END ) +
SUM( CASE HasGroup WHEN 1 THEN 1 ELSE 0 END )))*100), 2) AS NonGroupedPercentage,
ROUND(((SUM( CASE HasGroup WHEN 0 THEN 1 ELSE 0 END ) /
(SUM( CASE HasGroup WHEN 0 THEN 1 ELSE 0 END ) +
SUM( CASE HasGroup WHEN 1 THEN 1 ELSE 0 END )))*100), 2) /
(SELECT SUM(NonGroupedPercentage)
FROM (
SELECT
ROUND(((SUM( CASE HasGroup WHEN 0 THEN 1 ELSE 0 END ) /
(SUM( CASE HasGroup WHEN 0 THEN 1 ELSE 0 END ) +
SUM( CASE HasGroup WHEN 1 THEN 1 ELSE 0 END )))*100), 2) AS NonGroupedPercentage
FROM
apps
INNER JOIN store
ON (apps.Store = store.Store)
AND AppName !=''
GROUP BY AppName
) AS total) *100 AS AverageNonGroupedPercentage
FROM
apps
INNER JOIN store
ON (apps.Store = store.Store)
AND AppName !=''
GROUP BY AppName

Related

How to build a table which content becoming row

I would like to make a query on table as below:
enter image description here
b.sostatus required to become column title, and summarise the count of orderno
My SQL as below:
`
select
b.orderTime as orderDate,
sum( case when b.soStatus='00' then count(a.orderNo) else 0 end ) as Not_Allocated,
sum( case when b.soStatus='30' then count(a.orderNo) else 0 end ) as Partially_Allocated,
sum( case when b.soStatus='40' then count(a.orderNo) else 0 end ) as Allocated,
sum(case when b.soStatus='50' then count(a.orderNo) else 0 end ) as Partially_Picked ,
sum(case when b.soStatus='60' then count(a.orderNo) else 0 end ) as Picked,
sum(case when b.soStatus='63' then count(a.orderNo) else 0 end ) as Cartonized,
sum(case when b.soStatus='99' then count(a.orderNo) else 0 end ) as Closed,
case
when datediff(NOW(),b.orderTime) >=2 then '>=H-2'
when datediff(NOW(),b.orderTime) =1 then 'H-1'
when datediff(NOW(),b.orderTime) <1 then 'H' end as status
from DOC_ORDER_HEADER b
left join DOC_ORDER_DETAILS a
on
b.organizationId='ID_8COM'
and b.warehouseId='WHCPT01'
AND a.orderno = b.orderno
where b.organizationId='ID_8COM'
and b.warehouseId='WHCPT01'
`
However, it is popping error: Invalid use of group function
You don't need to use count() function on this requirement. sum(1) is enough to get the count based on your criteria.
select
b.orderTime as orderDate,
sum(case when b.soStatus='00' then 1 else 0 end) as Not_Allocated,
sum(case when b.soStatus='30' then 1 else 0 end) as Partially_Allocated,
sum(case when b.soStatus='40' then 1 else 0 end) as Allocated,
sum(case when b.soStatus='50' then 1 else 0 end) as Partially_Picked ,
sum(case when b.soStatus='60' then 1 else 0 end) as Picked,
sum(case when b.soStatus='63' then 1 else 0 end) as Cartonized,
sum(case when b.soStatus='99' then 1 else 0 end) as Closed,
case when datediff(NOW(),b.orderTime) >=2 then '>=H-2'
when datediff(NOW(),b.orderTime) = 1 then 'H-1'
when datediff(NOW(),b.orderTime) < 1 then 'H' end as status
from DOC_ORDER_HEADER b
left join DOC_ORDER_DETAILS a on b.organizationId='ID_8COM' and b.warehouseId='WHCPT01'
and a.orderno = b.orderno
where b.organizationId='ID_8COM'
and b.warehouseId='WHCPT01'
group by b.orderTime
You can also do this.
sum(b.soStatus='00')

MySQL SUM with CASE choose latest record by date

I've got the SUM CASE statements working properly. The issue is that I have multiple records with similar criteria, so I'd like to select the latest record by date.
SELECT
SUM(CASE WHEN planning like 'Rotation%' THEN 1 ELSE 0 END +
CASE WHEN assessmentanddata like 'Collects%' THEN 1 else 0 END +
CASE WHEN path like 'Same%' THEN 1 else 0 END +
CASE WHEN place like 'Move%' THEN 1 else 0 END +
CASE WHEN pace like 'Timer%' THEN 1 else 0 END +
CASE WHEN classroommanagement like 'Restating%' THEN 1 else 0 END +
CASE WHEN teacherrole like 'Mini%' THEN 1 else 0 END +
CASE WHEN studentengagement like 'Follow%' THEN 1 else 0 END +
CASE WHEN studentcollaboration like 'Collects%' THEN 1 else 0 END +
CASE WHEN technology like 'Technology%' THEN 1 else 0 END) AS p1
from ruberic where schoolId = 1
A sample from the table will be these 3 columns of DATE, SCHOOLID, and TEACHERID:
2016-12-05 1 1 -> This record will be fine
2016-12-05 1 4 -> Select only this when compared with the record below
2016-12-05 1 4
Building on what I see (I don't see the field name for date so assumed date)
This uses a correlates subquery and an exists statement to identify the max(date) for each teacherID and school and then limits the main dataset by this subset through the coloration.
SELECT
SUM(CASE WHEN planning like 'Rotation%' THEN 1 ELSE 0 END +
CASE WHEN assessmentanddata like 'Collects%' THEN 1 else 0 END +
CASE WHEN path like 'Same%' THEN 1 else 0 END +
CASE WHEN place like 'Move%' THEN 1 else 0 END +
CASE WHEN pace like 'Timer%' THEN 1 else 0 END +
CASE WHEN classroommanagement like 'Restating%' THEN 1 else 0 END +
CASE WHEN teacherrole like 'Mini%' THEN 1 else 0 END +
CASE WHEN studentengagement like 'Follow%' THEN 1 else 0 END +
CASE WHEN studentcollaboration like 'Collects%' THEN 1 else 0 END +
CASE WHEN technology like 'Technology%' THEN 1 else 0 END) AS p1
FROM
ruberic R1
WHERE
schoolId = 1
AND EXISTS (SELECT Null
FROM ruberic r2
WHERE R2.SchoolID = R1.SchoolID
AND R2.TeacherID = R1.TeacherID
GROUP BY SchoolID, TeacherID
HAVING R1.Date = MAX(R2.Date) )

How could I check the value of an aggregation function inside the same query?

This MySQL query gives me this error 'Unknown column 'winnings' in 'field list'
SELECT
o.user_id,
sum(case when o.result = 1 or o.result=2 or o.result = 0 then 1 else 0 end) as tahmins_no,
sum(case when o.result = 1 then 1 else 0 end) as winnings,
sum(case when o.result = 2 then 1 else 0 end) as loses,
sum(case when winnings = 10 then 0.5 else 0 end) as counter
FROM `odds_tahminler` o
I know that winnings is the value of the sum() aggregation function, But is there any way to check the winnings value within the query?
You can't use an aggregated column inside the select. However you can use a subquery to obtain the counter value after all the aggregated columns have been computed.
How is the counter value calculated? I assumed that the counter should be (winnings - 10) / 2 if there's at least 10 winnings and 0 otherwise. In that case you can obtain it with this query
SELECT O.*,
GREATEST( (O.winnings - 10) / 2, 0) as counter
FROM
(
SELECT u.username,
o.user_id,
sum(case when o.result = 1 or o.result=2 or o.result = 0 then 1 else 0 end) as tahmins_no,
sum(case when o.result = 1 then 1 else 0 end) as winnings,
sum(case when o.result = 2 then 1 else 0 end) as loses
FROM `odds_tahminler` o
) as O
you can try:
SELECT
o.user_id,
sum(case when o.result = 1 or o.result=2 or o.result = 0 then 1 else 0 end) as tahmins_no,
sum(case when o.result = 1 then 1 else 0 end) as winnings,
sum(case when o.result = 2 then 1 else 0 end) as loses,
sum(case when winnings = 10 then 0.5 else 0 end) as counter
FROM `odds_tahminler` o
GROUP BY o.user_id
HAVING counter>2

Is it possible to use SUM - CASE - IF together?

When I try to use this:
SUM(CASE WHEN IF(SUM(CASE WHEN "b.count_students_status" = 1 THEN 1 ELSE 0 END) >= 1, 1, 0) = 1 THEN 1 ELSE 0 END)
It says Query Error: Improper usage of Group Function
Below is the complete code:
SELECT
"a.batch" AS Batch,
SUM(
CASE
WHEN IF(
SUM(
CASE
WHEN "b.count_students_status" = 1
THEN 1
ELSE 0
END
) >= 1,
1,
0
) = 1
THEN 1
ELSE 0
END
) AS Payments_Not_Received
FROM
"DBU - Complete"
WHERE "a.suspended" = 'no'
GROUP BY "a.batch"
I wanted to convert the status to 1, if there are multiple occurrences and then sum the total occurrences.
Any help please - I am using ZOHO to build the query?
You're trying to reference the result of the GROUP BY before is has run. Try something like this:
select t.BATCH,
sum(case when t.pnr >=1 then 1 else 0 end) as Payments_Not_Received
from
(
select
a.batch as BATCH,
SUM(CASE WHEN "b.count_students_status" = 1 THEN 1
ELSE 0
END) as pnr
from yourTable a
WHERE a.suspended = 'no'
group by a.batch
) t
group by t.BATCH;

mySQL query comparing rows and columns

I have a database of user answers from a quiz which contains 8 questions. Q1 - Q8 all are their own columns, I'd like to compare all the rows and get a number back for everyone who answered the same for at least 5 questions.
so here, rows 5 and 6 would count as 2. Basically I'm trying to get a number for everyone who answered at least 5 questions the same. Is this possible with a mySQL query?
EDIT:
Here the user enters D B D A B C D B, matching with 2 similarly answered quizzes. The query here would return a count of 2.
If we test using just your single line of D B D A B C D B we can use the following example:
SELECT * FROM `answers` WHERE ((CASE WHEN q1 = 'D' THEN 1 ELSE 0 END) +
(CASE WHEN q2 = 'B' THEN 1 ELSE 0 END) +
(CASE WHEN q3 = 'D' THEN 1 ELSE 0 END) +
(CASE WHEN q4 = 'A' THEN 1 ELSE 0 END) +
(CASE WHEN q5 = 'B' THEN 1 ELSE 0 END) +
(CASE WHEN q6 = 'C' THEN 1 ELSE 0 END) +
(CASE WHEN q7 = 'D' THEN 1 ELSE 0 END) +
(CASE WHEN q8 = 'B' THEN 1 ELSE 0 END)) >= 5;
However, if we then want to go a step further and test each answer against the other answers in the table we can use the following statement:
SELECT *, (SELECT COUNT(answer_sub.idanswers) FROM `answers` answer_sub
WHERE ((CASE WHEN answer_sub.q1 = a.q1 THEN 1 ELSE 0 END) +
(CASE WHEN answer_sub.q2 = a.q2 THEN 1 ELSE 0 END) +
(CASE WHEN answer_sub.q3 = a.q3 THEN 1 ELSE 0 END) +
(CASE WHEN answer_sub.q4 = a.q4 THEN 1 ELSE 0 END) +
(CASE WHEN answer_sub.q5 = a.q5 THEN 1 ELSE 0 END) +
(CASE WHEN answer_sub.q6 = a.q6 THEN 1 ELSE 0 END) +
(CASE WHEN answer_sub.q7 = a.q7 THEN 1 ELSE 0 END) +
(CASE WHEN answer_sub.q8 = a.q8 THEN 1 ELSE 0 END)) >= 5
AND answer_sub.idanswers <> a.idanswers) as matching
FROM `answers` a
WHERE (SELECT COUNT(answer_sub.idanswers) FROM `answers` answer_sub
WHERE ((CASE WHEN answer_sub.q1 = a.q1 THEN 1 ELSE 0 END) +
(CASE WHEN answer_sub.q2 = a.q2 THEN 1 ELSE 0 END) +
(CASE WHEN answer_sub.q3 = a.q3 THEN 1 ELSE 0 END) +
(CASE WHEN answer_sub.q4 = a.q4 THEN 1 ELSE 0 END) +
(CASE WHEN answer_sub.q5 = a.q5 THEN 1 ELSE 0 END) +
(CASE WHEN answer_sub.q6 = a.q6 THEN 1 ELSE 0 END) +
(CASE WHEN answer_sub.q7 = a.q7 THEN 1 ELSE 0 END) +
(CASE WHEN answer_sub.q8 = a.q8 THEN 1 ELSE 0 END)) >= 5
AND answer_sub.idanswers <> a.idanswers) > 0
Because FALSE is 0 and TRUE is 1 in MySQL:
SELECT COUNT(*)
FROM quiz
WHERE ( (q1=#q1) + (q2=#q2) + (q3=#q3) + (q4=#q4)
+ (q5=#q5) + (q6=#q6) + (q7=#q7) + (q8=#q8)
) >= 5