自连接删除了几个表

Self Join Several Tables Removed

我有 4 个 table:resourcesfeature_resourcesfeaturesfeature_types

一个resource有很多features(使用feature_resources作为连接table),每个feature有一个feature_type

我需要检查一个特定的 resource 是否同时具有 featuresRESOURCE_TYPELIBRARY

我尝试了以下方法,但没有用:

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 答案都会很有趣。

数据

资源:

| 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         |

feature_types:

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

一种方法是使用聚合来确定您需要哪些资源: 类似于:

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

试试这个

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;