MYSQL JOIN с уникальными строками результатов - PullRequest
4 голосов
/ 19 апреля 2011

Допустим, у меня есть 2 таблицы, одна называется категориями, а другая - cat_pages.

Таблица категорий содержит идентификатор столбца, заголовок и метку времени.Например:

CREATE TABLE categories (
    id INT UNSIGNED PRIMARY KEY,
    title VARCHAR(32),
    `timestamp` TIMESTAMP,
    INDEX (title)
) Engine=InnoDB;

У cat_pages есть 2 столбца, cat_id и page_id:

CREATE TABLE cat_pages (
    cat_id INT UNSIGNED 
        REFERENCES categories (id) 
        ON DELETE CASCADE ON UPDATE CASCADE,
    page_id INT UNSIGNED
        REFERENCES pages (id) 
        ON DELETE CASCADE ON UPDATE CASCADE,
    UNIQUE INDEX (cat_id, page_id),
    INDEX (page_id, cat_id),
) Engine=InnoDB;

Я пытаюсь объединить таблицу категорий с таблицей cat_pages по идентификатору, так что

  1. Извлекаются только категории с идентификаторами в таблице category_pages и
  2. Каждая категория отображается только один раз в наборе результатов

Запрос:

SELECT * FROM categories as c
    LEFT JOIN cat_pages as p ON c.id = p.cat_id

создает набор результатов, в котором категории повторяются несколько раз (так как в таблице cat_pages есть несколько совпадений. Что мне нужно, чтобы каждая категория отображалась только один раз, а не вообще, если совпадений нетв таблице cat_pages?

Ответы [ 2 ]

11 голосов
/ 19 апреля 2011

Если вам не нужны категории, которых нет в cat_pages, не используйте левое соединение;использовать внутреннее соединение.Левое объединение включает в себя каждую строку из левой таблицы, даже если в правой таблице нет подходящей строки (отсутствующим полям даны значения NULL).Правое соединение аналогично, но включает все строки из правой таблицы.Внешнее соединение включает все строки из левой и правой таблиц, объединяя строки, которые имеют совпадения, и объединяя строки без совпадений со значениями NULL.Внутреннее соединение, напротив, включает только совпадающие строки.Другими словами, пересечение левого и правого соединений является внутренним соединением;их союз является внешним объединением.Джефф Этвуд опубликовал несколько хороших диаграмм Венна, описывающих объединения , хотя следует отметить, что наборы в кружках - это не левая и правая таблицы, а результаты левого и правого соединений левогои правильные таблицы.

Чтобы получить отдельные строки, вы можете использовать модификатор DISTINCT:

SELECT DISTINCT c.* 
  FROM categories AS c 
    INNER JOIN cat_pages AS cp ON c.id = cp.cat_id

Что касается SELECT * ..., см. " Почему нетиспользуйте select *?"

Другим подходом к получению отдельных строк будет использование предложения EXISTS или оператора IN, но соединениевероятно, более производительный (хотя наверняка вам скажет только EXPLAIN).Просто убедитесь, что у вас установлены соответствующие индексы.

0 голосов
/ 19 апреля 2011

Почему бы вам не использовать Inner Join?

SELECT * FROM categories as c INNER JOIN cat_pages as p ON c.id = p.cat_id

Или

SELECT * FROM categories as c LEFT JOIN cat_pages as p ON c.id = p.cat_id WHERE p.cat_id IS NOT NULL

Left Join выбирает все в левой таблице и совпадения в правой таблице.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...