2015-04-23 3 views
0

У меня есть 4 стола: resources, feature_resources, features и feature_types.Self Join Несколько столов Удалено

resource имеет много features (с использованием feature_resources в качестве соединения таблицы), и каждый feature имеет feature_type.

мне нужно проверить, если конкретный resource имеет и features как с RESOURCE_TYPE и LIBRARY.

Я попытался следующие, но это не сработало:

SELECT * FROM resources 
INNER JOIN feature_resources ON feature_resources.resource_id = resources.id 
INNER JOIN features AS f1 ON f1.id = feature_resources.feature_id 
INNER JOIN features AS f2 ON f2.id = feature_resources.feature_id 
INNER JOIN feature_types AS ft1 ON ft1.id = f1.feature_type_id 
INNER JOIN feature_types AS ft2 ON ft2.id = f2.feature_type_id 
WHERE ft1.value = 'RESOURCE_TYPE' 
AND ft2.value = 'LIBRARY' 

Я думаю, что проблема в том, что feature.id будет отличаться только resource.id будет то же самое. Я пробовал вышеуказанный код с LEFT JOIN, и он все еще не работал.

Мое текущее решение является подзапрос подход:

SELECT "resources".* 
FROM "resources" 
INNER JOIN feature_resources ON feature_resources.resource_id = resources.id 
INNER JOIN features AS featureTwo ON featureTwo.id = feature_resources.feature_id 
INNER JOIN feature_types AS featureTypeTwo ON featureTwo.feature_type_id = featureTypeTwo.id 
WHERE "resources"."id" 
    IN 
    (SELECT "resources"."id" 
    FROM "resources" 
    INNER JOIN feature_resources ON feature_resources.resource_id = resources.id 
    INNER JOIN features AS featureOne ON feature_resources.feature_id = featureOne.id 
    INNER JOIN feature_types AS featureTypeOne ON featureOne.feature_type_id = 
    featureTypeOne.id 
    WHERE (featureOne.string_value = 'ZONE') 
    AND (featureTypeOne.value = 'RESOURCE_TYPE')) 
AND (featureTypeTwo.value = 'LIBRARY') 

Это работает, просто интересно, если есть способ, чтобы использовать внутренние соединения, а не вложенных запросах.

Я использую postgres, но любой общий ответ SQL будет интересен.

DATA

ресурсы:

| id | description | 
| 1 | Office  | 

feature_resources:

| resource_id | feature_id | 
|  1  |  1  | 
|  1  |  2  | 

Особенности:

| id | string_value | feature_type_id | 
| 1 | Zone  |  1   | 
| 2 | nil  |  2   | 

F eature_types:

| id | value   | 
| 1 | RESOURCE_TYPE | 
| 2 | LIBRARY  | 

ответ

0

Один подход заключается в использовании заполнителей, чтобы определить, какие ресурсы вам нужно: что-то вроде:

select resources.id, resources.description 
from 
    resources 
join 
feature_resources 
on 
    resources.id = feature_resources.resource_id 
join 
    features 
on 
    feature_resources.features_id = features.id 
join 
    feature_types 
on 
    features.feature_type_id = feature_types.id 
where 
    feature_types.value in ('RESOURCE_TYPE', 'LIBRARY') 
group by 
    resources.id, resources.description 
having 
    count(*) = 2 
+0

ли это убедиться, что я был один ' RESOURCE_TYPE 'и одной «БИБЛИОТЕК», или было бы возможно, что если ресурс имел 2 записи «RESOURCE_TYPE», это все равно было бы отмечено как действительное? –

+0

как написано, любые 2 - но вы можете пойти с 'count (distinct feature_types.id)', если возможны дубликаты –

0

Тест

select 
    r.* 
from 
    feature_resources fr 

    inner join resources r on 
    r.id = fr.resource_id 

    inner join features f on 
    f.id = fr.feature_id 

    inner join feature_types ft on 
    ft.id = f.feature_type_id 
where 
    ft.value in ('resource_type', 'library') 
group by 
    r.id 
having 
    count(*) = 2; 
+0

Я получаю сообщение об ошибке, что 'column" r.id "должен появиться в предложении GROUP BY или использоваться в совокупной функции ». Я думаю, что мы должны изменить 'group by' немного –

+0

Просто добавьте' r.id' в предложение group by и удалите 'fr.resource_id' –