MySQL фильтрация результатов с использованием левого внешнего соединения - PullRequest
1 голос
/ 18 апреля 2010

мой запрос:

        SELECT content.*, activity_log.content_id FROM content
        LEFT JOIN activity_log 
        ON content.id = activity_log.content_id 
        AND sess_id = '$sess_id'
        WHERE activity_log.content_id IS NULL
        AND visibility = $visibility
        AND content.reported < ".REPORTED_LIMIT."
        AND content.file_ready = 1
        LIMIT 1

Цель этого запроса - получить 1 строку из таблицы содержимого, которая не была просмотрена пользователем (идентифицирована с помощью session_id), но она по-прежнему возвращает просмотренное содержимое. Что случилось? (Я проверил таблицу, убедившись, что content_ids там есть)

Примечание: я думаю, что это более эффективно, чем использование подзапросов, мысли?

1 Ответ

1 голос
/ 19 апреля 2010

Проблема, очевидно, в вашем состоянии JOIN. Используемая вами оптимизация (применение условия к базовой таблице) имеет смысл, когда вас интересуют результаты внутреннего соединения, но в случае внешнего JOIN это читается следующим образом: находите соответствия между строками content и activity_log, когда идентификатор содержимого совпадает и идентификатор сеанса совпадает, и возвращает пустые значения для строк activity_log, когда либо отсутствует журнал для идентификатора содержимого, либо отсутствует идентификатор содержимого, но идентификатор сеанса не соответствует указанному . И это вряд ли то, что вы хотите.

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

SELECT content.*, activity_log.content_id
FROM (
SELECT *
FROM content
WHERE sess_id = '$sess_id'
    AND visibility = $visibility
    AND file_ready = 1
    AND reported < ".REPORTED_LIMIT."
) as content
LEFT JOIN activity_log 
ON content.id = activity_log.content_id 
WHERE activity_log.content_id IS NULL
LIMIT 1;

Если производительность не оптимальна, вы можете рассмотреть возможность создания составного индекса (sess_id, видимость, fileready, сообщил).

...