MAX, SUM, а затем AVG в одном SQL-запросе?

Вопрос: Сложный SQL-запрос нужен здесь, но не уверен, что это возможно. У меня есть таблица вроде этого: ------------------------ |uid |lesson_id |score | ------------------------ |1 |0 |20 | |1 |0 |25 | |1 |0 |15 | |1 |0 |40 | |1 |1 |70 | |1 |0 |10 | |1 |1 |20 | |1 |1 |55 |

Вопрос:

Сложный SQL-запрос нужен здесь, но не уверен, что это возможно.

У меня есть таблица вроде этого:

———————— |uid |lesson_id |score | ———————— |1 |0 |20 | |1 |0 |25 | |1 |0 |15 | |1 |0 |40 | |1 |1 |70 | |1 |0 |10 | |1 |1 |20 | |1 |1 |55 | |1 |1 |55 | |1 |0 |5 | |1 |2 |65 | ————————

Для конкретного пользователя мне нужно получить максимальный балл для каждого урока, суммировать их, а затем получить их среднее… все в одном SQL-запросе.

Макс. Оценки:

———————— |lesson_id |max_score | ———————— |0 |40 | |1 |70 | |2 |65 | ————————

Сумма:

—— |sum | —— |175 | ——

В среднем:

——- |avg | ——- |58.3 | ——-

Как это?

SELECT uid AS id, AVG(max_score) AS avg_score FROM ( SELECT uid, lesson_id, max(score) AS max_score FROM cdu_user_progress WHERE session_id = $session_id GROUP BY uid, lesson_id ) AS tt WHERE uid IN ($ids) GROUP BY uid ORDER BY avg_score Лучший ответ:

Вы можете просто использовать подзапросы:

SELECT uid, SUM(MaxScore), Avg(MaxScore) FROM ( SELECT uid, lesson_id,max(score) as MaxScore FROM scores GROUP BY userid, lesson_id ) AS m GROUP BY uid

или только для одного пользователя:

SELECT SUM(MaxScore), Avg(MaxScore) FROM ( SELECT lesson_id,max(score) as MaxScore FROM scores WHERE uid = $uid GROUP BY lesson_id ) AS m

или для “группы конкретных пользователей”:

$uidlist = (comma-delimited list of user ids) SELECT uid, SUM(MaxScore), Avg(MaxScore) FROM ( SELECT uid, lesson_id,max(score) AS MaxScore FROM scores WHERE FIND_IN_SET(uid, $uidlist) GROUP BY uid, lesson_id ) AS m GROUP BY uid Ответ №1

Вот простой пример SQLFIDDLE

select Avg(tt.maxscores) from ( select lesson_id,max(score) as maxscores from t group by lesson_id ) as tt Ответ №2SELECT AVG( s.scores ) AS avarage, SUM( s.scores ) AS total FROM ( SELECT lesson_id, MAX( score ) AS scores FROM ‘tblScores’ GROUP BY lesson_id ) AS s Ответ №3

Вы можете легко сделать это в одном SQL-запросе, хотя вам понадобится использовать более одного оператора.

Наиболее легко, вы можете сделать это через подзапрос, хотя тот же результат можно сделать с помощью временной таблицы или Common-Table-Expression.

(Также обратите внимание, что функция SQL AVG уже суммирует и делит результаты по их счету. Вы не хотите делать AVG(SUM(X)), так как это приведет к бессмысленной фигуре.) В любом случае, на пример:

Сначала напишите выражение SQL, чтобы получить элементы, которые вы будете усреднять, например максимальный балл для каждого теста для каждого пользователя.

SELECT MAX(Score) As MaxScore, uid, lesson_id FROM table GROUP BY uid, lesson_id

Затем вы обрабатываете вышеуказанный SELECT как таблицу и делаете второй выбор вокруг него, чтобы получить средний балл за uid.

SELECT AVG(MaxScore) as Final, uid FROM ( SELECT MAX(Score) As MaxScore, uid, lesson_id FROM table GROUP BY uid, lesson_id ) AS subQuery GROUP BY uid

Вы можете легко включить дополнительные функции агрегации с помощью этого метода, и, поскольку он довольно стандартный, он будет работать на большинстве SQL-серверов. Однако, в зависимости от поставщика, у вас может быть собственный синтаксис, созданный специально для этого, например, OVER и Parition на SQL Server

Ответ №4

Все возможно, это может быть очень очень уродливо. Вот пример уродливого кода, который может получить то, что вы хотите в одном запросе…

Запрос кода PSEUDO:

SELECT lesson_id, max_score WHERE uid=X UNION SELECT -1, sum //done via nested query UNION SELECT -2, average //done via nested query

Оцените статью
Добавить комментарий