У меня есть две таблицы,
одна таблица называется 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)
но ничего из этого не работает.
Это не работает так, как вы думаете, и документация объясняет значение 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
вместо. Индексы в числовых столбцах работают быстрее и занимают меньше места, чем индексы в строковых столбцах.
Других решений пока нет …