2016-02-08 3 views
0

Я пытаюсь выбрать элементы, которые не имеют определенного значения в другой таблице, я смог достичь результата, который я хотел, используя подзапрос, однако это очень медленно, так что я интересно, если я мог бы сделать это по-другому ...Выберите элементы, которые не имеют определенного значения в другой таблице

SELECT 
    content.*, 
    (SELECT views 
    FROM content_views 
    WHERE content_views.content = content.record_num 
    ) as views 
FROM content 
RIGHT JOIN watch_log ON content.record_num = watch_log.content 
WHERE content.enabled = 1 
    AND 24 NOT IN 
     (SELECT niche 
     FROM content_niches 
     WHERE content_niches.content = content.record_num 
     ) 
ORDER BY content.encoded_date 
DESC LIMIT 0,6 

Я попытался с помощью LEFT OUTER JOIN, но не может получить тот же результат ...

SELECT 
    content.*, 
    (SELECT content_views.views 
    FROM content_views 
    WHERE content_views.content = content.record_num 
    ) as views 
FROM content 
RIGHT JOIN watch_log ON content.record_num = watch_log.content 
LEFT OUTER JOIN content_niches ON content.record_num = content_niches.content AND content_niches.niche = 24 
WHERE content.enabled = 1 
ORDER BY content.encoded_date 
DESC LIMIT 0,6 
+1

Почему это ПРАВИЛЬНОЕ СОЕДИНЕНИЕ?!? – jarlh

+0

Особенно, если есть условие WHERE content.enabled = 1 – Shadow

ответ

0

Смешение левое и правое внешние соединения просто сбивают с толку. Фактически, right join на самом деле не нужен. Его обычно можно заменить на left join. В вашем случае его можно заменить внутренним соединением, потому что предложение where превращает его в внутреннее соединение. Итак, как насчет:

SELECT c.*, 
     (SELECT views 
     FROM content_views cv 
     WHERE cv.content = c.record_num 
     ) as views 
FROM content c JOIN 
    watch_log wl 
    ON c.record_num = wl.content 
WHERE c.enabled = 1 AND 
     NOT EXISTS (SELECT 1 
        FROM content_niches cn 
        WHERE cn.content = c.record_num AND 
         cn.niche = 24 
       ) 
ORDER BY c.encoded_date DESC 
LIMIT 0, 6; 

Для производительности вы хотите индексы: content(enabled, encoded_date, record_num), content_views(content, views) и content_niches(content, niche).

Примечания:

  • Не смешивайте различные типы внешних соединений, если вы действительно, действительно понимают, что они делают.
  • Используйте псевдонимы таблиц, которые сокращают имена таблиц. Это упрощает чтение и чтение запросов.
  • Независимо от ваших предпочтений при форматировании, не начинайте строку в запросе с DESC (или ASC); это модификатор на ORDER BY.
  • NOT EXISTS лучше, чем NOT IN. Бывшие ручки NULL оценивают то, как вы ожидали. Последний не возвращает ничего, если есть значения NULL.
+0

Итак, как вы указали, все столбцы уже были проиндексированы как BTREE. Но почему вы не указали направление JOIN? – Dacramash

+0

@ Dacramash. , , Я не уверен, что вы имеете в виду. Для соединения не требуется «направление», потому что это «внутреннее соединение». –

Смежные вопросы