Это возвращает правильные результаты (NULL
) для меня:
CREATE TABLE users_values (id INT NOT NULL PRIMARY KEY, user_id INT NOT NULL, another_id INT NOT NULL, created DATETIME NOT NULL);
INSERT
INTO users_values VALUES (1, 9917, 23, '2010-01-01');
SELECT *,
(
SELECT id
FROM users_values AS ParentUsersValue
WHERE ParentUsersValue.user_id = UsersValue.user_id
AND ParentUsersValue.another_id = UsersValue.another_id
AND ParentUsersValue.id < UsersValue.id
ORDER BY id
DESC
LIMIT 1
) AS old_id
FROM users_values AS UsersValue
WHERE created >= '2009-12-20'
AND created <= '2010-01-21'
AND user_id = 9917
AND another_id = 23
Не могли бы вы выполнить этот запрос:
SELECT COUNT(*)
FROM users_values AS UsersValue
WHERE user_id = 9917
AND another_id = 23
и убедитесь, что он возвращает 1
?
Обратите внимание, что ваш подзапрос не фильтруется на created
, поэтому подзапрос может возвращать значения вне диапазона, определенного основным запросом.
Обновление:
Это определенно ошибка в MySQL
.
Скорее всего, причина в том, что путь доступа, выбранный для UsersValues
, равен index_intersect
.
Выбирает подходящие диапазоны из обоих индексов и строит их пересечение.
Из-за ошибки зависимый подзапрос оценивается до завершения пересечения, поэтому вы получаете результаты с правильным another_id
, но с неправильным user_id
.
Не могли бы вы проверить, сохраняется ли проблема при принудительном сканировании PRIMARY
на UsersValues
:
SELECT *,
(
SELECT id
FROM users_values AS ParentUsersValue
WHERE ParentUsersValue.user_id = UsersValue.user_id
AND ParentUsersValue.another_id = UsersValue.another_id
AND ParentUsersValue.id < UsersValue.id
ORDER BY id
DESC
LIMIT 1
) AS old_id
FROM users_values AS UsersValue FORCE INDEX (PRIMARY)
WHERE created >= '2009-12-20'
AND created <= '2010-01-21'
AND user_id = 9917
AND another_id = 23
Кроме того, для этого запроса вы должны создать составной индекс для (user_id, another_id, id)
, а не два отдельных индекса для user_id
и another_id
.
Создайте индекс и немного перепишите запрос:
SELECT *,
(
SELECT id
FROM users_values AS ParentUsersValue
WHERE ParentUsersValue.user_id = UsersValue.user_id
AND ParentUsersValue.another_id = UsersValue.another_id
AND ParentUsersValue.id < UsersValue.id
ORDER BY
user_id DESC, another_id DESC, id DESC
LIMIT 1
) AS old_id
FROM users_values AS UsersValue
WHERE created >= '2009-12-20'
AND created <= '2010-01-21'
AND user_id = 9917
AND another_id = 23
Предложения user_id DESC, another_id DESC
логически избыточны, но они сделают индекс для использования при заказе.