【问题标题】:Selecting rows that are included in a set from another table从另一个表中选择包含在集合中的行
【发布时间】:2016-06-21 17:23:54
【问题描述】:

我有一个带有产品名称和 ID 的表“产品”:

id    |  title
1        product 1
2        product 2

每个产品都可以有一系列标签。标签在“属性”表中标识:

id |   name     | handle
1      Tag One    tag-one
2      Tag Two    tag-two
3      Tag Three  tag-three
4      Tag Four   tag-four
etc

产品到标签的关系是另一个表“标签”:

id  | AttId | OwnerId
1       1        1
2       2        1
3       1        2
4       3        2
etc

好的,所以我正在尝试选择一组都具有至少一个特定标签的产品,以及可能选择的其他标签。这是我现在正在使用的:

SELECT products.id
FROM products
WHERE
EXISTS
( 
    SELECT  1
    FROM Tags
    INNER JOIN Attributes ON tags.AttId = Attributes.id
    WHERE Attributes.handle = 'tag-one'
    AND (
            Attributes.handle = 'tag-two'
            OR
            Attributes.handle = 'tag-four'
        )

    AND products.id = Tags.OwnerId
)

如果我删除 AND (OR) 部分,则查询有效。如上,它没有显示错误,但也没有结果;我应该怎么写才能得到一组肯定有一个标签的产品,并且标签句柄有一个/或其他指定的标签?

【问题讨论】:

    标签: mysql sql join exists


    【解决方案1】:

    我喜欢使用group byhaving 来解决这类问题——因为我发现这种方法非常适合表达许多不同的条件。根据您的条件:

    select p.*
    from products p join
         tags t
         on t.OwnerId = p.id join
         attributes a
         on t.attid = a.id
    group by p.id
    having sum(a.handle = 'tag-one') > 0 and
           sum(a.handle in ('tag-two', 'tag-four')) > 0;
    

    having 子句中的每个条件都会计算匹配条件的行数(对于产品)。第一个说至少有一行带有'tag-one' 句柄。第二个表示至少有一行与其他两个句柄。

    【讨论】:

      【解决方案2】:

      我认为,如果您执行两个单独的查询并取交集,那将给您想要的结果。

      -- Get all the owner ids that have 'tag-one'
      select OwnerId
      from Tags t1
      where AttId in
      (
        select id
        from Attributes a1
        where a1.handle = 'tag-one'
      )
      intersect
      -- Get all the owner ids that have tag-two and tag-four
      select OwnerId
      from Tags t2
      where AttId in
      (
        select id
        from Attributes a2
        where a2.handle in ('tag-two', 'tag-four')
      )
      ;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-19
        • 2023-03-20
        • 1970-01-01
        • 2022-11-10
        • 1970-01-01
        • 2015-01-10
        • 1970-01-01
        相关资源
        最近更新 更多