Использование функции MIN () с INNER JOIN - PullRequest
0 голосов
/ 30 декабря 2018

У меня есть маленький вопрос.Я провожу курс Data Science SQL на Coursera и имею следующую задачу:

Задача 7: Используя INNER JOIN, найдите минимальную «Среднюю посещаемость учащихся» для области сообщества, где трудности составляют 96.

Я решил проблему следующим образом:

SELECT S.AVERAGE_STUDENT_ATTENDANCE, S.COMMUNITY_AREA_NAME, C.HARDSHIP_INDEX
FROM CHICAGO_PUBLIC_SCHOOLS as S
INNER JOIN CENSUS_DATA as C
ON C.COMMUNITY_AREA_NUMBER = S.COMMUNITY_AREA_NUMBER
WHERE C.HARDSHIP_INDEX = 96
ORDER BY S.AVERAGE_STUDENT_ATTENDANCE ASC
LIMIT 1;

Однако изначально я хотел решить ее элегантно без ORDER BY и LIMIT.Функция MIN(S.AVERAGE_STUDENT_ATTENDANCE) не работает для меня - я получаю сообщение об ошибке:

An expression starting with "HARDSHIP_INDEX" specified in a SELECT clause, HAVING clause, or ORDER BY clause is not specified in the GROUP BY clause or it is in a SELECT clause, HAVING clause, or ORDER BY clause with a column function and no GROUP BY clause is specified.. SQLCODE=-119, SQLSTATE=42803, DRIVER=4.24.92

Есть ли способ решить проблему с помощью MIN?

Большое спасибо.

Ответы [ 2 ]

0 голосов
/ 30 декабря 2018

Ваш метод является правильным методом для использования.Однако вы можете использовать трюк group_concat() / substring_index(), если вы действительно хотите:

SELECT MAX(S.AVERAGE_STUDENT_ATTENDANCE),
       SUBSTRING_INDEX(GROUP_CONCAT(S.COMMUNITY_AREA_NAME ORDER BY S.AVERAGE_STUDENT_ATTENDANCE ASC), ',', 1),
       SUBSTRING_INDEX(GROUP_CONCAT(C.HARDSHIP_INDEX ORDER BY S.AVERAGE_STUDENT_ATTENDANCE ASC), ',', 1)
FROM CHICAGO_PUBLIC_SCHOOLS S INNER JOIN
     CENSUS_DATA  C
     ON C.COMMUNITY_AREA_NUMBER = S.COMMUNITY_AREA_NUMBER
WHERE C.HARDSHIP_INDEX = 96;
0 голосов
/ 30 декабря 2018

Способ использования min выглядит следующим образом:

SELECT
    S.AVERAGE_STUDENT_ATTENDANCE
  , S.COMMUNITY_AREA_NAME
  , C.HARDSHIP_INDEX
FROM CHICAGO_PUBLIC_SCHOOLS AS S
INNER JOIN CENSUS_DATA AS C ON C.COMMUNITY_AREA_NUMBER = S.COMMUNITY_AREA_NUMBER
WHERE C.HARDSHIP_INDEX = 96
AND S.AVERAGE_STUDENT_ATTENDANCE = (
    SELECT
        MIN( S.AVERAGE_STUDENT_ATTENDANCE )
    FROM CHICAGO_PUBLIC_SCHOOLS AS S
    INNER JOIN CENSUS_DATA AS C ON C.COMMUNITY_AREA_NUMBER = S.COMMUNITY_AREA_NUMBER
    WHERE C.HARDSHIP_INDEX = 96
)

В зависимости от используемой базы данных, если она поддерживает общие выражения таблиц, вы можете сделать это:

WITH cte
AS (
    SELECT
        S.AVERAGE_STUDENT_ATTENDANCE
      , S.COMMUNITY_AREA_NAME
      , C.HARDSHIP_INDEX
    FROM CHICAGO_PUBLIC_SCHOOLS AS S
    INNER JOIN CENSUS_DATA AS C ON C.COMMUNITY_AREA_NUMBER = S.COMMUNITY_AREA_NUMBER
    WHERE C.HARDSHIP_INDEX = 96
)
SELECT
    *
FROM cte
WHERE AVERAGE_STUDENT_ATTENDANCE = (
    SELECT
        MIN( AVERAGE_STUDENT_ATTENDANCE )
    FROM cte
)

Если ваша версия MySQL поддерживает оконные функции (v8 или новее), то может также работать что-то вроде этого:

SELECT
    AVERAGE_STUDENT_ATTENDANCE
  , COMMUNITY_AREA_NAME
  , HARDSHIP_INDEX
FROM (
    SELECT
        S.AVERAGE_STUDENT_ATTENDANCE
      , S.COMMUNITY_AREA_NAME
      , C.HARDSHIP_INDEX
      , MIN( S.AVERAGE_STUDENT_ATTENDANCE ) OVER () AS min_att
    FROM CHICAGO_PUBLIC_SCHOOLS AS S
    INNER JOIN CENSUS_DATA AS C ON C.COMMUNITY_AREA_NUMBER = S.COMMUNITY_AREA_NUMBER
    WHERE C.HARDSHIP_INDEX = 96
) sq
WHERE AVERAGE_STUDENT_ATTENDANCE = min_att

Примечание OVER(), т.е. ничего внутри предложения over, не разрешено во всех базах данных, это можетвместо этого нужно что-то вроде over(partition by C.HARDSHIP_INDEX).

...