Выполнение нескольких запросов в MySQL без использования подзапроса

У меня есть две таблицы,
одна таблица называется users с,

fsname
emailaddress

и вторая таблица называется attempts с emailaddress, score а также datetime,

Теперь, что я хотел сделать, это сначала заказать attempts таблица по datetime а затем выбрать, затем присоединиться к attempt стол с users таблица, если они имеют одинаковые emailaddress а затем выберите последние попытки каждого уникального пользователя.

Короче говоря, я должен выбрать последнюю попытку каждого пользователя, присоединившись к этой таблице, и это запрос, который я сгенерировал для достижения этой цели,

$query = "SELECT
distinct users.fsname, users.emailaddress, attempts.score
FROM users
INNER JOIN attempts
ON users.emailaddress = attempts.emailaddress
ORDER BY datetime DESC";

Этот запрос сначала предполагает заказать attempts от datetime и только выбрать значения с отличным именем, которое fsname здесь.

но когда я выполняю приведенный выше запрос, он возвращает результат с неуникальными значениями fsname хотя я использую DISTINCT с fsname,

Может кто-нибудь, пожалуйста, скажите мне, почему DISTINCT не работает, чтобы выбрать только разные fsname ?

Я пробовал оба DISTINCT fsname а также DISTINCT(fsname) но ничего из этого не работает.

1

Решение

Это не работает так, как вы думаете, и документация объясняет значение DISTINCT: это о четких строки:

ALL а также DISTINCT параметры указывают, должны ли возвращаться повторяющиеся строки. ALL (по умолчанию) указывает, что должны быть возвращены все соответствующие строки, включая дубликаты. DISTINCT Определяет удаление повторяющихся строк из набора результатов. Ошибочно указывать оба варианта. DISTINCTROW это синоним DISTINCT,

(источник: http://dev.mysql.com/doc/refman/5.7/en/select.html)

Вам нужно сгруппировать строки по пользователю, чтобы получить по одной строке для каждого пользователя, но, к сожалению, вы не можете получить их самую последнюю оценку таким образом.
Вы можете получить максимальный, минимальный, средний балл и другие вычисленные значения. Проверьте список GROUP BY агрегатные функции.

Запрос

Это запрос, который получает нужные вам значения:

SELECT u.fsname, u.emailaddress, la.score
FROM users u
INNER JOIN attempts la                # 'la' from 'last attempt'
ON u.emailaddress = la.emailaddress
LEFT JOIN attempts mr                 # 'mr' from 'more recent' (than last attempt)
ON la.emailaddress = mr.emailaddress AND la.datetime < mr.datetime
WHERE mr.datetime IS NULL

Как это устроено

Присоединяется к таблице users (с псевдонимом как u) со столом attempts (с псевдонимом как laсокращение от «последняя попытка») emailaddress как соответствующий столбец. Это соединение, которое у вас уже есть в вашем запросе, я добавил псевдонимы, потому что они помогают вам писать меньше с этого момента.

Далее он присоединяется к attempts стол снова (с псевдонимом как mr от «более свежий чем последняя попытка «). Соответствует каждой попытке la со всеми попытками mr одного и того же пользователя (определяется их emailaddress) а также которые имеют более свежий datetime, LEFT JOIN гарантирует, что каждый ряд из la соответствует хотя бы одной строке из mr, Строки из la которые не имеют совпадения в mr строки, которые имеют самые большие значения datetime для каждого emailaddress, Они сопоставлены с рядами, полными NULL (для mr часть).

Наконец, WHERE предложение сохраняет только те строки, которые имеют NULL в datetime столбец строки, выбранной из mr, Это строки, которые соответствуют самым последним записям из la для каждого значения emailaddress,

Замечания по производительности

Чтобы быстро выполнить этот запрос (любой запрос!) нужны индексы для столбцов, используемых в JOIN, WHERE, GROUP BY а также ORDER BY статьи.

Вы не должны использовать emailaddress в таблице attempts идентифицировать пользователя. Вы должны иметь PK (первичный ключ) на столе users и использовать это как FK (внешний ключ) в таблице attempts (и другие таблицы, которые ссылаются на пользователя). Если emailaddress это PK стола users изменить его на UNIQUE INDEX и использовать новый INTEGER AUTO INCREMENTред колонка userId как PK вместо. Индексы в числовых столбцах работают быстрее и занимают меньше места, чем индексы в строковых столбцах.

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]