Многие условия в предложении WHERE SQL-запроса - PullRequest
0 голосов
/ 01 марта 2011

Привет, у меня проблемы с написанием запроса.Я буду очень рад получить совет!

Моя таблица называется TagObjects;у него есть 5 столбцов, но 3 важных для проблемы: tob_tag, tob_object и tob_objectType.

Что мне нужно достичь с помощью запроса: с неизвестным количеством пар (tob_object, tob_objectType)нужно знать все tob_tag, которые есть у всех пар.

Я пытался с этим запросом (цифры приведены только в качестве примера):

SELECT "TagsObjects"."tob_tag"
FROM "TagsObjects"
WHERE TRUE
AND ("TagsObjects"."tob_object" = 8 AND "TagsObjects"."tob_objecttype" = 1)
AND ("TagsObjects"."tob_object" = 9 AND "TagsObjects"."tob_objecttype" = 1)
GROUP BY "TagsObjects"."tob_tag";

ГДЕ ИСТИНА, потому что я строю запрос динамически.Этот запрос работает для одной пары (один оператор AND в предложении WHERE), когда я пробовал его с двумя парами (как в примере, который я публикую выше), он не возвращает никаких строк (и данные есть!).

Если кто-то знает, что я делаю неправильно или как это сделать, это будет БОЛЬШАЯ ПОМОЩЬ!

Использование PostgreSQL 9.0.1.

Ответы [ 2 ]

2 голосов
/ 01 марта 2011

При создании необязательных предложений делайте их, используя этот шаблон

ВЫБЕРИТЕ "TagsObjects". "Tob_tag"
ОТ "ТегиОбъекты"
ГДЕ ЛОЖЬ
ИЛИ ("TagsObjects". "Tob_object" = 8 И "TagsObjects". "Tob_objecttype" = 1)
ИЛИ ("TagsObjects". "Tob_object" = 9 И "TagsObjects". "Tob_objecttype" = 1)
GROUP BY "TagsObjects". "Tob_tag";

Однако, если условий вообще нет, добавьте OR TRUE в список, чтобы он стал

ВЫБЕРИТЕ "TagsObjects". "Tob_tag"
ОТ "ТегиОбъекты"
ГДЕ ЛОЖЬ
ИЛИ ИСТИНА
GROUP BY "TagsObjects". "Tob_tag";

Что касается этой части

Мне нужно знать все теги tob_tag, которые есть у всех пар.

Если вы хотите, чтобы tob_tags имели и 8/1 и 9/1 (или более комбинаций), то вам нужны предложения GROUP BY и HAVING.

SELECT "TagsObjects"."tob_tag"
FROM "TagsObjects"
WHERE FALSE
OR ("TagsObjects"."tob_object" = 8 AND "TagsObjects"."tob_objecttype" = 1)
OR ("TagsObjects"."tob_object" = 9 AND "TagsObjects"."tob_objecttype" = 1)
GROUP BY "TagsObjects"."tob_tag"
HAVING COUNT(*) = 2;
1 голос
/ 01 марта 2011

Давайте начнем с того, что не так. Вы пытаетесь найти строку, в которой оба "TagsObjects". "Tob_object" = 8 и "TagsObjects". "Tob_object" = 9. "TagsObjects". "Tob_object" не могут быть одновременно одновременно, поэтому не могут быть возвращены никакие строки ,

Что тебе тогда делать?

Из вашей спецификации я понял, что есть несколько пар ("TagsObjects". "Tob_object", "TagsObjects". "Tob_objectType"), где ни одно из полей не является константой. Вы хотите создать объединение всех строк, которые возвращаются для каждой пары.

WITH matchingTagsObjects AS (
    SELECT "TagsObjects"."tob_tag" 
    FROM "TagsObjects" 
    WHERE ("TagsObjects"."tob_object" = 8 AND "TagsObjects"."tob_objecttype" = 1)
    UNION ALL
    SELECT "TagsObjects"."tob_tag" 
    FROM "TagsObjects" 
    WHERE ("TagsObjects"."tob_object" = 9 AND "TagsObjects"."tob_objecttype" = 1)
 )
 SELECT "TagsObjects"."tob_tag"  
 FROM matchingTagsObjects
 GROUP BY "TagsObjects"."tob_tag";

Именованный подзапрос matchTgsObjects перечисляет все теги tob_tags, найденные для пар (8,1) и (8,2). Фактические теги выбираются в основном запросе, а отдельные теги tob_tags выбираются с помощью предложения group by, как и в вашем решении. Я использовал UNION ALL, потому что группировка выполняется в основном запросе, и я не нашел причин для удаления дублирующих строк в подзапросе на этом этапе. Вы можете достичь этого, исключив ALL из UNION ALL.

Вы также можете включить подзапрос непосредственно в часть from вместо использования именованного подзапроса.

Существует также альтернатива, в которой вы используете условия OR в предложении where, как в WHERE (соответствует паре A) OR (соответствует паре B). Мой коллега стал бы баллистиком, если бы увидел, что используется: когда для сопоставления в этом сценарии требуется ИЛИ, это говорит о том, что с реальной моделью можно что-то сделать.

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