Get the maximum value in a table

I have a very difficult problem. Let me first explain what I am doing right now:

I have a table name feedback

in which I store grades by course ID. The table looks like this:

+-------+-------+-------+-------+-----------+--------------
| id    | cid   | grade |g_point| workload  | easiness
+-------+-------+-------+-------+-----------+--------------
| 1     |  10   |  A+   |   1   |      5    |   4
| 2     |  10   |  A+   |   1   |      2    |   4
| 3     |  10   |  B    |   3   |      3    |   3
| 4     |  11   |  B+   |   2   |      2    |   3
| 5     |  11   |  A+   |   1   |      5    |   4
| 6     |  12   |  B    |   3   |      3    |   3
| 7     |  11   |  B+   |   2   |      7    |   8
| 8     |  11   |  A+   |   1   |      1    |   2

      

g_point

only has specific values ​​for grades, so I can use those values ​​to show custom courses sorted by grade.

Ok, now my task first is to print grade

each course. grade

can be calculated to the maximum in each course. For example, from this table you can see that the result cid = 10

will be A+

because it is present two times there. It's simple. I have already fulfilled this query which I will write here at the end.

The main problem is when we are talking about a course cid = 11

that has two different classes. Now in this situation the client asks me to take the average of the workload and ease of both of these courses, and whichever of the courses has the higher average should be shown. The average will be calculated as follows:

  all workload values of the grade against course
+ all easiness values of the grade against course
/ 2 

      

This example cid = 11

has four records, has an equal number of course grades

B+

middle class

avgworkload(2 + 7)/2=x 
avgeasiness(3 + 8)/2 = y

      

answer x + y / 2 = 10

A+

middle class

 avgworkload(5 + 1)/2=x 
avgeasiness(4 + 2)/2 = y

  answer x+y/2 = 3

      

so the class should be B+

.

This is the query I run to get the maximum match class

SELECT
    f3.coursecodeID cid,
    f3.grade_point p,
    f3.grade g
FROM (
    SELECT
        coursecodeID,
        MAX(mode_qty) mode_qty
    FROM (
        SELECT
            coursecodeID,
            COUNT(grade_point) mode_qty
        FROM feedback
        GROUP BY
            coursecodeID, grade_point
    ) f1
    GROUP BY coursecodeID
) f2
INNER JOIN (
    SELECT
        coursecodeID,
        grade_point,
        grade,
        COUNT(grade_point) mode_qty
    FROM feedback
    GROUP BY
        coursecodeID, grade_point
) f3
ON
    f2.coursecodeID = f3.coursecodeID AND
    f2.mode_qty = f3.mode_qty
GROUP BY f3.coursecodeID
ORDER BY f3.grade_point

      

+3


source to share


2 answers


Here is the SQL Fiddle . I've added a table Courses

listing all course IDs to make it easier to see the main idea of ​​the query. Chances are you have this in a real database. If not, you can generate it on the fly from feedback

grouping cid

.

For each cid

we need to find grade

. Group feedback

on cid, grade

to get a list of all ratings for cid

. We only need to select one class for cid

, so we use LIMIT 1

. To determine which class to choose, we order them. First, the introduction is simple COUNT

. Secondly, according to the average score. Finally, if there are multiple classes that have the same appearance and the same GPA, then choose the class with the lowest g_point

. You can customize the rules by changing the sentence ORDER BY

.

SELECT
  courses.cid
  ,(
    SELECT feedback.grade
    FROM feedback
    WHERE feedback.cid = courses.cid
    GROUP BY
      cid
      ,grade    
    ORDER BY 
      COUNT(*) DESC
      ,(AVG(workload) + AVG(easiness))/2 DESC
      ,g_point
    LIMIT 1
  ) AS CourseGrade
FROM courses
ORDER BY courses.cid

      

result set

cid CourseGrade
10  A+
11  B+
12  B

      

UPDATE

MySQL has no side joins, so one possible way to get the second column g_point

is by repeating the correlated subquery. SQL Fiddle



SELECT
  courses.cid
  ,(
    SELECT feedback.grade
    FROM feedback
    WHERE feedback.cid = courses.cid
    GROUP BY
      cid
      ,grade    
    ORDER BY 
      COUNT(*) DESC
      ,(AVG(workload) + AVG(easiness))/2 DESC
      ,g_point
    LIMIT 1
  ) AS CourseGrade
  ,(
    SELECT feedback.g_point
    FROM feedback
    WHERE feedback.cid = courses.cid
    GROUP BY
      cid
      ,grade    
    ORDER BY 
      COUNT(*) DESC
      ,(AVG(workload) + AVG(easiness))/2 DESC
      ,g_point
    LIMIT 1
  ) AS CourseGPoint
FROM courses
ORDER BY CourseGPoint

      

result set

cid CourseGrade CourseGPoint
10  A+          1
11  B+          2
12  B           3

      

Update 2 Added average score in ORDER BY

SQL Fiddle

SELECT
  courses.cid
  ,(
    SELECT feedback.grade
    FROM feedback
    WHERE feedback.cid = courses.cid
    GROUP BY
      cid
      ,grade    
    ORDER BY 
      COUNT(*) DESC
      ,(AVG(workload) + AVG(easiness))/2 DESC
      ,g_point
    LIMIT 1
  ) AS CourseGrade
  ,(
    SELECT feedback.g_point
    FROM feedback
    WHERE feedback.cid = courses.cid
    GROUP BY
      cid
      ,grade    
    ORDER BY 
      COUNT(*) DESC
      ,(AVG(workload) + AVG(easiness))/2 DESC
      ,g_point
    LIMIT 1
  ) AS CourseGPoint
  ,(
    SELECT (AVG(workload) + AVG(easiness))/2
    FROM feedback
    WHERE feedback.cid = courses.cid
    GROUP BY
      cid
      ,grade    
    ORDER BY 
      COUNT(*) DESC
      ,(AVG(workload) + AVG(easiness))/2 DESC
      ,g_point
    LIMIT 1
  ) AS AvgScore
FROM courses
ORDER BY CourseGPoint, AvgScore DESC

      

result

cid CourseGrade CourseGPoint    AvgScore
10  A+          1               3.75
11  B+          2               5
12  B           3               3

      

+1


source


If I understood correctly, you need an inner selection to find the mean, and a second outer selection to find the maximum values ​​of the mean

select cid, grade, max(average)/2 from (
    select cid, grade, avg(workload + easiness) as average
    from feedback
    group by cid, grade
) x group by cid, grade

      

This solution was tested on your sql account in your link

If you changed the previous request to

select cid,  max(average)/2 from (
    select cid, grade, avg(workload + easiness) as average
    from feedback
    group by cid, grade
) x group by cid

      



You will find the maximum average for each cid.

As mentioned in the comments, you should choose a usage strategy if you have more ratings that match the maximum average. For example, if you have

+-------+-------+-------+-------+-----------+--------------
| id    | cid   | grade |g_point| workload  | easiness
+-------+-------+-------+-------+-----------+--------------
| 1     |  10   |  A+   |   1   |      5    |   4
| 2     |  10   |  A+   |   1   |      2    |   4
| 3     |  10   |  B    |   3   |      3    |   3
| 4     |  11   |  B+   |   2   |      2    |   3
| 5     |  11   |  A+   |   1   |      5    |   4
| 9     |  11   |  C    |   1   |      3    |   6

      

You will have A + and C grades not exceeding the maximum average of 4.5

0


source







All Articles