获取连接表ID匹配的记录,或者是id列表的子集

时间:2015-03-10 21:44:14

标签: mysql sql ruby-on-rails ruby-on-rails-4 join

我有一个名为 variants 的表,它通过名为 option_values_variants的表以多对多关系连接到另一个名为 option_values 的表 EM>

我想在已加入的 option_values 表中提取所有变种,其中包含特定的id子集。通过示例更容易演示:

表格数据:

变体

id |      name
--------------
 1 | Tennant
 2 | Smith
 3 | Eccleston
 4 | Hurt

option_values

id | name
---------
80 | blue
81 | red
82 | green
83 | 64 gb
84 | 128 gb
85 | 256 gb
86 | short
87 | long

option_values_variants

variant_id | option_value_id
----------------------------
         1 | 80
         1 | 85
         1 | 86
         2 | 82
         2 | 85
         2 | 87
         3 | 80
         3 | 84
         3 | 86
         4 | 81
         4 | 83
         4 | 86

在这个例子中,我希望得到所有具有选项值的变体" blue"和"短",特别是(所以选项值ids 80和86)。

预期结果应该是变体" Tennant"和#34; Eccleston",因为这些变体同时具有" blue"和"短",尽管每个都有一个不同的选项值。 "伤害"有"短"但是没有" blue",所以他应该被排除在外," Smith"既没有。

在Rails上下文或纯SQL中,我似乎在形成这个查询方面有一点脑块。我似乎无法弄清楚如何指定"只有当连接表的id匹配或者是目标参数列表的子集时才应该进行连接#34;。这是我目前的尝试:

@product.variants.joins(:option_values).where(option_values: {id: [80, 86]}).uniq

生成SQL查询:

SELECT DISTINCT `variants`.* FROM `variants` 
INNER JOIN `option_values_variants` ON `option_values_variants`.`variant_id` = `variants`.`id` 
INNER JOIN `option_values` ON `option_values`.`id` = `option_values_variants`.`option_value_id` 
WHERE `variants`.`product_id` = 32 AND `option_values`.`id` IN (80, 86)

由于查询正在执行WHERE ... IN (),因此它不会产生所需的结果。使用上面的例子,我将返回" Tennant"," Eccleston"和" Hurt"然而" Hurt"不属于,因为它不包含选项值" blue" (或选项值id 80)。

如何选择联接表行匹配的记录或者是给定ID列表的子集?

此外,它可能是所述大脑阻滞的结果,但不可否认,我可能不会很好地解释这一点。如果我没有任何意义,请告诉我

1 个答案:

答案 0 :(得分:1)

您可以使用group by并指定结果的选项值均为having count(distinct option_values.id) = 2

   SELECT
        v.id,
        v.name
    FROM variants v
        INNER JOIN option_values_variants ov
            ON ov.variant_id = v.id 
        INNER JOIN option_values o
            ON o.id = ov.option_value_id 
    WHERE v.product_id = 32
        AND o.id IN (80, 86)
    GROUP BY
        v.id,
        v.name
    HAVING COUNT(DISTINCT o.id) = 2