MySQL SUM with CASE choose latest record by date - mysql

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) )

Related

How can I simplify this mysql query, based on 2 tables?

after 2 days of trial and error, I just completed this mysql query. It works fine, but it does look really hideous. Is it possible to simplify my query ? All help is of course greatly appreciated.
SELECT
p.*,
COUNT(oT.Ontmoeting_ID) + COUNT(oU.Ontmoeting_ID) AS 'played',
COUNT(case oT.Ontmoeting_Uitploeg_FF when 1 then 1 else case oT.Ontmoeting_Thuisploeg_Bonus when 3 then 1 else null end end)
+ COUNT(case oU.Ontmoeting_Thuisploeg_FF when 1 then 1 else case oU.Ontmoeting_Uitploeg_Bonus when 3 then 1 else null end end)
- COUNT(case oU.Ontmoeting_Thuisploeg_FF when 1 then case oU.Ontmoeting_Uitploeg_FF when 1 then 1 else null end end)
- COUNT(case oT.Ontmoeting_Uitploeg_FF when 1 then case oT.Ontmoeting_Thuisploeg_FF when 1 then 1 else null end end) AS 'won',
COUNT(case oT.Ontmoeting_Thuisploeg_Bonus when 1 then 1 else null end) +
COUNT(case oU.Ontmoeting_Uitploeg_Bonus when 1 then 1 else null end) AS 'draw',
COUNT(case oU.Ontmoeting_Uitploeg_FF when 1 then 1 else case oU.Ontmoeting_Uitploeg_Bonus when 0 then 1 else null end end)
+ COUNT(case oT.Ontmoeting_Thuisploeg_FF when 1 then 1 else case oT.Ontmoeting_Thuisploeg_Bonus when 0 then 1 else null end end) AS 'lost',
SUM(COALESCE(oT.Ontmoeting_Thuisploeg_Totaal, 0)) + SUM(COALESCE(oU.Ontmoeting_Uitploeg_Totaal, 0)) AS 'Totaal'
FROM ploegen AS p
LEFT OUTER JOIN ontmoetingen AS oT ON oT.Ontmoeting_Thuisploeg_ID = p.Ploeg_ID AND oT.Ontmoeting_Competitie_ID = 1 and oT.Ontmoeting_Speelweek <= 2 AND (oT.Ontmoeting_Thuisploeg_Totaal > 0 OR oT.Ontmoeting_Thuisploeg_FF = 1)
LEFT OUTER JOIN ontmoetingen AS oU ON oU.Ontmoeting_Uitploeg_ID = p.Ploeg_ID and oU.Ontmoeting_Competitie_ID = 1 AND oU.Ontmoeting_Speelweek <= 2 AND (oU.Ontmoeting_Uitploeg_Totaal > 0 OR oU.Ontmoeting_Uitploeg_FF = 1)WHERE p.Ploeg_ID IN (select Ontmoeting_Thuisploeg_ID from ontmoetingen WHERE Ontmoeting_Competitie_ID = 1)
GROUP BY p.Ploeg_ID
ORDER BY totaal DESC
The query is based on 2 tables, "ontmoetingen" and "ploegen" (in English: "encounters" and "teams"). It calculates the overall standings of the teams, adding all played, won and draw encounters. The main difficulty is that all teams play both home and away games and those have to be summarized ("Thuisploeg" = "Home Team", "Uitploeg" = "Away Team". Please let me know if more info on the tables is required to help me out. Thx !
Table: "Ontmoetingen":
Table: "ploegen":
Expected output:
All numbers in output are fictional, so not corresponding to table data. Hope this helps !

MySQL How to count columns containing specified column value

I have the table xyz
ID day1 day2 day3 day4
1 A A P P
2 A A A P
3 A A A A
4 A P P P
I want to be able to query this and return the ID with the number of columns that have A as their value in that row. So the result would look like this:
ID Count
1 2
2 3
3 4
4 1
Here is a trick you can use involving string concatenation:
SELECT
ID,
CHAR_LENGTH(CONCAT(day1, day2, day3, day4)) -
CHAR_LENGTH(REPLACE(CONCAT(day1, day2, day3, day4), 'A', '')) AS Count
FROM yourTable
ORDER BY ID;
Demo
If you want to count other letters as well, just duplicate the logic I have for the letter A, e.g. for L we can try:
CHAR_LENGTH(CONCAT(day1, day2, day3, day4)) -
CHAR_LENGTH(REPLACE(CONCAT(day1, day2, day3, day4), 'L', ''))
This is simple to accomplish applying case to all columns and usmming them up! Try below:
select id,
case day1 when 'A' then 1 else 0 end +
case day2 when 'A' then 1 else 0 end +
case day3 when 'A' then 1 else 0 end +
case day4 when 'A' then 1 else 0 end `CountA`,
case day1 when 'L' then 1 else 0 end +
case day2 when 'L' then 1 else 0 end +
case day3 when 'L' then 1 else 0 end +
case day4 when 'L' then 1 else 0 end `CountL`,
case day1 when 'P' then 1 else 0 end +
case day2 when 'P' then 1 else 0 end +
case day3 when 'P' then 1 else 0 end +
case day4 when 'P' then 1 else 0 end `CountP`
from Tbl

MySQL CASE WHEN where clause causes failure

I have a complex query that does multiple matches across multiple columns and then orders by relevance.
Everything works fine UNTIL I add WHERE 'rank' > 0
This then returns an empty results set.
If I remove the 'WHERE' statement then I can see all results with the highest matches at the top.
Could someone help me work out 'WHERE' :-D I am going wrong!!
SELECT *, CASE WHEN companyName = 'gfdgfs' THEN 2 ELSE 0 END
+ CASE WHEN companyName LIKE '%gfdgfs%' THEN 1 ELSE 0 END
+ CASE WHEN companyName = 'potato' THEN 2 ELSE 0 END
+ CASE WHEN companyName LIKE '%potato%' THEN 1 ELSE 0 END
+ CASE WHEN address1 = 'gfdgfs' THEN 2 ELSE 0 END
+ CASE WHEN address1 LIKE '%gfdgfs%' THEN 1 ELSE 0 END
+ CASE WHEN address1 = 'potato' THEN 2 ELSE 0 END
+ CASE WHEN address1 LIKE '%potato%' THEN 1 ELSE 0 END
AS rank
FROM clients
WHERE rank > 0
ORDER BY rank
EDIT
I removed the single quotes around the rank word and now get 'unknown column rank in where clause'
Remove single quotes from rank and try. Anyway, I don't think MySQL would support WHERE clause with aliases - check this.
Use HAVING rather than WHERE:
SELECT *, CASE WHEN companyName = 'gfdgfs' THEN 2 ELSE 0 END
+ CASE WHEN companyName LIKE '%gfdgfs%' THEN 1 ELSE 0 END
+ CASE WHEN companyName = 'potato' THEN 2 ELSE 0 END
+ CASE WHEN companyName LIKE '%potato%' THEN 1 ELSE 0 END
+ CASE WHEN address1 = 'gfdgfs' THEN 2 ELSE 0 END
+ CASE WHEN address1 LIKE '%gfdgfs%' THEN 1 ELSE 0 END
+ CASE WHEN address1 = 'potato' THEN 2 ELSE 0 END
+ CASE WHEN address1 LIKE '%potato%' THEN 1 ELSE 0 END
AS rank
FROM clients
HAVING rank > 0
ORDER BY rank
Try this:
SELECT *
FROM (SELECT *, CASE WHEN companyName = 'gfdgfs' THEN 2 ELSE 0 END
+ CASE WHEN companyName LIKE '%gfdgfs%' THEN 1 ELSE 0 END
+ CASE WHEN companyName = 'potato' THEN 2 ELSE 0 END
+ CASE WHEN companyName LIKE '%potato%' THEN 1 ELSE 0 END
+ CASE WHEN address1 = 'gfdgfs' THEN 2 ELSE 0 END
+ CASE WHEN address1 LIKE '%gfdgfs%' THEN 1 ELSE 0 END
+ CASE WHEN address1 = 'potato' THEN 2 ELSE 0 END
+ CASE WHEN address1 LIKE '%potato%' THEN 1 ELSE 0 END
AS rank
FROM clients
) AS A
WHERE rank > 0
ORDER BY rank;

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;

count the numbers of differences in each columns with data reference impossible?

I need to count the sum of the differences between a set of known data. The equivalent in php is
(count(array_diff_assoc($array1)). Is this possible with Mysql? I have a set of data to compare with each others field column in the table.
my data to compare is columnA : 3, columnB : 6, columnC : 4
the test table is :
ID columnA columnB columnC
1 2 6 1
2 6 1 3
3 3 6 4
result expected :
ID numbersofdifferences
3 0
1 2
2 3
thanks for any help,
Jesisca
This is not necessarily the cleanest but you could use an aggregate function with a CASE expression:
select id,
sum(case when columna = 3 then 0 else 1 end) +
sum(case when columnb = 6 then 0 else 1 end) +
sum(case when columnc = 4 then 0 else 1 end) TotalDiff
from yourtable
group by id;
See SQL Fiddle with Demo.
Edit, this could be done without the aggregate function as well:
select id,
(case when columna = 3 then 0 else 1 end) +
(case when columnb = 6 then 0 else 1 end) +
(case when columnc = 4 then 0 else 1 end) TotalDiff
from yourtable;
See Demo
There isn't a function built in to do something like that, but you could do it manually.
select
id,
case columnA when $columnA then 1 else 0 end +
case columnB when $columnB then 1 else 0 end +
case columnC when $columnC then 1 else 0 end differences
from
myTable
But if you want them in order, you'll want a subselect
select * from
(
select
id,
case columnA when $columnA then 1 else 0 end +
case columnB when $columnB then 1 else 0 end +
case columnC when $columnC then 1 else 0 end differences
from
myTable
) sqlRequiresNameHere
order by differences