【问题标题】:Self Join Several Tables Removed自联接删除了几个表
【发布时间】:2015-04-23 15:23:46
【问题描述】:

我有 4 个表:resourcesfeature_resourcesfeaturesfeature_types

一个resource 有很多features(使用feature_resources 作为连接表),每个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       |

【问题讨论】:

    标签: sql postgresql join subquery


    【解决方案1】:

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

    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
    

    【讨论】:

    • 这会确保我有一个“RESOURCE_TYPE”和一个“LIBRARY”,还是有可能如果一个资源有 2 个“RESOURCE_TYPE”条目,这仍然会被标记为有效?
    • 如所写,任意 2 - 但如果可能重复,您可以使用 count(distinct feature_types.id)
    【解决方案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;
    

    【讨论】:

    • 我收到column "r.id" must appear in the GROUP BY clause or be used in an aggregate function 的错误。我想我们必须稍微改变一下group by
    • 只需将r.id添加到group by子句并删除fr.resource_id
    猜你喜欢
    • 1970-01-01
    • 2011-06-27
    • 1970-01-01
    • 2013-11-08
    • 1970-01-01
    • 1970-01-01
    • 2020-06-03
    • 2016-07-04
    • 1970-01-01
    相关资源
    最近更新 更多