通过三个表INNER JOIN中的多个AND子句匹配多行的SQL查询

时间:2015-10-04 22:53:05

标签: sql postgresql

很抱歉,如果我的标题不是很具体。我只是不知道这叫什么,因为我倾向于让Rails为我提取数据库查询,更复杂的问题让我感到厌烦。我有这个生成rails的查询:

SELECT "stocks".* FROM "stocks" INNER JOIN "parts" ON "parts"."id" = "stocks"."part_id" 
INNER JOIN "features" ON "features"."part_id" = "parts"."id" INNER JOIN "feature_titles" ON "feature_titles"."id" = "features"."feature_title_id" 
WHERE "parts"."category_id" = 20 AND "stocks"."manufacturer_id" = 4 
AND ((feature_titles.title = 'Title One' AND (features.value = '0.1' OR features.value = '1')) AND (feature_titles.title = 'Title Two' AND (features.value = '200')))

重点:

parts(id, number, category_id)

features(id, value, feature_title_id, part_id)

feature_titles(id, title)

快速解释:

每个部分都可以有多个功能。每个功能都属于feature_title。现在我需要我的查询来获取具有与其各自feature_titles相关联的那些功能的所有部分。使用上面的例子:

parts
---------
id number

1   some part number
2   some other part
features (values aren't strictly integers)
--------------
id  values  feature_title_id  part_id

1     0.1        1               1
2      1         2               1
3     7 MAX      2               2
4     0.1        1               2
feature_titles
-------------------
id  title

1    Title One
2    Title Two

执行以下查询有效。

SELECT "stocks".* FROM "stocks" INNER JOIN "parts" ON "parts"."id" = "stocks"."part_id" 
INNER JOIN "features" ON "features"."part_id" = "parts"."id" INNER JOIN "feature_titles" ON "feature_titles"."id" = "features"."feature_title_id" 
WHERE "parts"."category_id" = 20 AND "stocks"."manufacturer_id" = 4 
AND ((feature_titles.title = 'Title One' AND (features.value = '0.1' OR features.value = '1')))

它返回带有id的部分1.但是如果我想通过添加另一个feature_title和其他功能(参见第一个问题查询)来进一步过滤,则返回0行。我希望它返回相同的单行(在本例中)。我真的不明白,因为我认为AND和OR运算符是如何工作的。除非我遗漏了什么。

修改

对不起伙计们,我正在添加另一个更清楚的例子。忽略连接,因为它似乎是关键所在:

feature_titles.title = 'Title One' AND 
    (features.value = '0.1' OR features.value = '1')

应返回id为1 AND 2的部分。但查询

(feature_titles.title = 'Title One' AND (features.value = '0.1')) 
    AND (feature_titles = 'Title Two' AND (features.value = '7 MAX'))

只应返回ID为2的部分。

4 个答案:

答案 0 :(得分:1)

我认为你需要聚合:

SELECT s.*
FROM "stocks" s INNER JOIN
     "parts" p
     ON p."id" = s."part_id" INNER JOIN
     "features" f
     ON f."part_id" = p."id" INNER JOIN
     "feature_titles" ft
     ON ft."id" = f."feature_title_id" 
WHERE p."category_id" = 20 AND s."manufacturer_id" = 4 AND
      ft.title = 'Title One' AND
      (f.value = '0.1' OR f.value = '1')
GROUP BY s.stock_id  -- may need to include all columns here
HAVING COUNT(DISTINCT f.value) = 2;  -- makes sure you get both of them

答案 1 :(得分:1)

我真的没有看到所有嵌套的parens中的重点。而且我删除了引号,因为它们让我的注意力有点分散。

import java.util.regex.*;

    if (subjectString.matches("AB|BCD1|B11|BL:|B/1:|B1L:|B11:")) {
        System.out.println(s);
        String nextLine = br.readLine();
        System.out.println(nextLine);
    }

查看示例数据和查询,我无法确定WHERE parts.category_id = 20 AND stocks.manufacturer_id = 4 AND ( feature_titles.title = 'Title One' AND features.value IN ('0.1', '1') OR feature_titles.title = 'Title Two' AND features.value = '200' ) 的{​​{1}}来自何处。我想知道你是否也没有这样的东西。

value

第二个查询比第一个查询宽松,但我认为你已经说了一些关于搜索过滤器的信息。

您在问题中提到“进一步过滤”。无法再将任何结果过滤掉。但不要担心,在我的经验中,对AND / OR的混淆似乎很常见。这是因为我们以非技术方式在英语口语中使用这些术语的方式。

答案 2 :(得分:1)

内部查询找到符合条件的要素,然后按部件ID对其进行分组。匹配功能位于不同的数据行中,以验证某个部件是否符合多个条件,您必须计算该组中的行数。

SELECT stocks.*
FROM stocks
WHERE part_id IN (
    SELECT part_id
    FROM
        parts ON parts.id = stocks.part_id
        INNER JOIN features ON features.part_id = parts.id
        INNER JOIN feature_titles ON feature_titles.id = features.feature_title_id 
    WHERE
            parts.category_id = 20 AND stocks.manufacturer_id = 4
        AND (
                feature_titles.title = 'Title One' AND features.value = '0.1'
            OR  feature_titles.title = 'Title Two' AND features.value = '7 MAX'
        )
    GROUP BY parts.id
    HAVING COUNT(features.id) = 2
)

答案 3 :(得分:0)

中心AND应为OR。你基本上要求同时拥有“Title One”和“Title Two”的东西。但它只能是一个或另一个。 试试这个:

'200'