Присоединяясь к 3 таблицам с отношением n: m, хочу видеть несопоставимые строки - PullRequest
0 голосов
/ 04 ноября 2011

Для этой проблемы рассмотрим следующие 3 таблицы:

Event
id (pk)
title

Event_Category
event_id (pk, fk)
category_id (pk, fk)

Category
id (pk)
description

Довольно тривиально, я думаю ... :) Каждое событие может попасть в ноль или более категорий, всего есть 4 категории. В моем приложении я хочу просматривать и редактировать категории для определенного события. Графически событие будет отображаться вместе со ВСЕМИ категориями и флажком, указывающим, попадает ли событие в категорию. Изменение и сохранение выбора приведет к модификации промежуточной таблицы Event_Category. Но сначала: как выбрать это для конкретного события? Запрос, который мне нужен, на самом деле всегда будет возвращать 4 строки, количество имеющихся категорий.

После возвращает только записи для категорий, в которые попадает событие с id = 11. Эксперимент с внешними объединениями не дал больше строк в результате.

SELECT e.id, c.omschrijving 
FROM Event e
  INNER JOIN Event_Categorie ec ON e.id = ec.event_id
  INNER JOIN Categorie c ON c.id = ec.categorie_id
WHERE e.id = 11

Или я должен начать с таблицы категорий в запросе? Надеюсь на некоторые подсказки :) ТИА, Клаас

UPDATE: Да, но я все еще не нашел ответ. Но я упростил эту проблему, исключив таблицу «Событие» из запроса, поскольку эта таблица используется только для просмотра описаний событий.

SELECT * from Categorie c LEFT JOIN Event_Categorie ec ON c.id = ec.categorie_id WHERE ec.event_id = 11;

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

Ответы [ 4 ]

0 голосов
/ 08 ноября 2011

Наконец-то я нашел правильный запрос, никакой подвыборки не требуется. Но предложение WHERE работает после объединения и, следовательно, больше не является частью объединения. Решение расширяет предложение ON с дополнительным условием. Теперь все 4 строки возвращаются с NULL для несоответствующих категорий!

SELECT * 
FROM Categorie  
LEFT JOIN Event_Categorie ON categorie_id = id AND event_id = 11;

Таким образом, суть в том, что добавление дополнительного условия в предложение ON имеет иной эффект, чем фильтрация строк по тому же условию в предложении WHERE!

0 голосов
/ 08 ноября 2011

Запрос

SELECT * FROM Categorie;

возвращает 4 строки:

+----+--------------+-------------------------------------+--------------------------------------+
| id | omschrijving | afbeelding                          | afbeelding_klein                     |
+----+--------------+-------------------------------------+--------------------------------------+
|  1 | Creatief     | images/categorieen/creatief420k.jpg | images/categorieen/creatief190k.jpg  |
|  2 | Sportief     | images/categorieen/sportief420k.jpg | images/categorieen/sportief190kr.jpg |
|  4 | Culinair     | images/categorieen/culinair420k.jpg | images/categorieen/culinair190k.jpg  |
|  5 | Spirit       | images/categorieen/spirit420k.jpg   | images/categorieen/spirit190k.jpg    |
+----+--------------+-------------------------------------+--------------------------------------+
4 rows in set (0.00 sec)

НО: Запрос

SELECT * 
FROM Categorie 
LEFT JOIN Event_Categorie ON categorie_id = id 
WHERE event_id = 11;

возвращает 2 строки:

+----+--------------+-------------------------------------+-------------------------------------+----------+--------------+
| id | omschrijving | afbeelding                          | afbeelding_klein                    | event_id | categorie_id |
+----+--------------+-------------------------------------+-------------------------------------+----------+--------------+
|  1 | Creatief     | images/categorieen/creatief420k.jpg | images/categorieen/creatief190k.jpg |       11 |            1 |
|  4 | Culinair     | images/categorieen/culinair420k.jpg | images/categorieen/culinair190k.jpg |       11 |            4 |
+----+--------------+-------------------------------------+-------------------------------------+----------+--------------+
2 rows in set (0.00 sec)

Так что мне все еще нужен подзапрос ... и LEFT JOIN не эффективен для отображения всех строк таблицы CAtegorie, независимо от того, есть ли совпадение с таблицей ссылок.

Этот запрос, однако, выполняет то, что я хочу:

SELECT * 
FROM Categorie c 
LEFT JOIN (SELECT * FROM Event_Categorie ec WHERE ec.event_id = 11 ) AS subselect ON  subselect.categorie_id = c.id;

Результат:

+----+--------------+-------------------------------------+--------------------------------------+----------+--------------+
| id | omschrijving | afbeelding                          | afbeelding_klein                     | event_id | categorie_id |
+----+--------------+-------------------------------------+--------------------------------------+----------+--------------+
|  1 | Creatief     | images/categorieen/creatief420k.jpg | images/categorieen/creatief190k.jpg  |       11 |            1 |
|  2 | Sportief     | images/categorieen/sportief420k.jpg | images/categorieen/sportief190kr.jpg |     NULL |         NULL |
|  4 | Culinair     | images/categorieen/culinair420k.jpg | images/categorieen/culinair190k.jpg  |       11 |            4 |
|  5 | Spirit       | images/categorieen/spirit420k.jpg   | images/categorieen/spirit190k.jpg    |     NULL |         NULL |
+----+--------------+-------------------------------------+--------------------------------------+----------+--------------+
4 rows in set (0.00 sec)
0 голосов
/ 08 ноября 2011

Проблема в том, что вы отфильтровали результаты по вечернему времени. Как видно из результатов, две категории (Sportief и Spirit) не имеют событий. Таким образом, правильный оператор SQL (с использованием синтаксиса SQL Server; может потребоваться перевод):

SELECT * 
FROM Categorie 
LEFT JOIN Event_Categorie ON categorie_id = id 
WHERE (event_id IS NULL) OR (event_id = 11);
0 голосов
/ 08 ноября 2011

То, что вы хотите, это список всех категорий, плюс информация о том, есть ли эта категория в списке категорий вашего мероприятия.

Итак, вы можете сделать:

SELECT 
    * 
FROM 
    Category 
    LEFT JOIN Event_Category ON category_id = id 
WHERE 
    event_id = 11

и столбец event_id будет иметь значение NULL для категорий, которые не являются частью вашего события.

Вы также можете создать столбец (с именем has_category ниже), который вы будете использовать, чтобы увидеть, имеет ли событие эту категорию вместо сравнения сNULL:

SELECT 
    *,
    event_id IS NOT NULL AS has_category
FROM 
    Category 
    LEFT JOIN Event_Category ON category_id = id 
WHERE 
    event_id = 11

РЕДАКТИРОВАТЬ: Это кажется именно то, что вы говорите, что вы делаете на редактирование.Я проверил это, и это кажется правильным.Вы уверены, что выполняете этот запрос, и что строки с NULL как-то не игнорируются?

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