【问题标题】:select rows in a one to many situation在一对多的情况下选择行
【发布时间】:2009-04-28 07:49:51
【问题描述】:

我认为我陷入了这种特殊情况:

这是我的桌子:

item_table:
编号 |项目
1:A
2:乙
3:C

属性表:
属性 | item_id
1 : 1
1 : 2
2 : 1
2 : 3
3 : 2
3 : 3
我想知道在技术上是否可以检索与 attr = 1 和 3 关联的任何项目。答案应该只是“B”。 同样,如果我请求与 attr = 1 和 2 相关联的项目,我应该只得到“A”。

问题是 attr_table 可能有很多行,我希望只进行一次查询。

这个问题听起来很简单,我为无法回答而感到很沮丧。

我希望更聪明的人能帮我一把……

【问题讨论】:

    标签: mysql select


    【解决方案1】:

    该示例是为 SQLServer 编写的,但查询也应该在 mysql 中工作。

    键是 HAVING COUNT 语句等于必须匹配的属性数量。如果属性应为 (1, 2, 5),则必须将计数更改为 3。

    DECLARE @item_table TABLE (ID INTEGER PRIMARY KEY, Item CHAR(1))
    DECLARE @attr_table TABLE (Attr INTEGER, Item_ID INTEGER)
    
    INSERT INTO @item_table VALUES (1, 'A')
    INSERT INTO @item_table VALUES (2, 'B')
    INSERT INTO @item_table VALUES (3, 'C')
    
    INSERT INTO @attr_table VALUES (1, 1)
    INSERT INTO @attr_table VALUES (1, 2)
    INSERT INTO @attr_table VALUES (2, 1)
    INSERT INTO @attr_table VALUES (2, 3)
    INSERT INTO @attr_table VALUES (3, 2)
    INSERT INTO @attr_table VALUES (3, 3)
    
    
    SELECT Item
    FROM @item_table i
         INNER JOIN @attr_table a ON a.Item_ID = i.ID
    WHERE a.Attr IN (1, 3)
    GROUP BY Item
    HAVING COUNT(a.Attr) = 2
    

    【讨论】:

    • 进行内部连接不就等于第二次选择吗?
    • 这是脆弱的,使用count =,因为除非有两个属性行对应于具有指定属性的项目,否则它将不起作用。但更糟糕的是,如果有两个 attr 行的 item_id = 1 和 attr = 1,它会失败——所以它会返回一个误报,即一个没有 attr = 3 的项目。它会增加 group 的成本。
    • @Blank Xavier,很抱歉,我不明白你想要表达什么。
    • @tpdi,我假设 attr_table 中的 (Attr, Item_ID) 存在唯一约束。
    【解决方案2】:
       SELECT * From attr_table a, item_table i
       where a.item_id = i.id
       and a.attr = 1
       and a.item_id  in (select item_id from attr_table where  attr = 3);  
    

    作业是否为项目 B 返回一行。

    【讨论】:

      【解决方案3】:
      select * from item_table a 
      where exists ( select * from attr_table b 
                     where b.item_id = a.id and b.attr = 1)
      and exists ( select * from attr_table c 
                   where c.item_id = a.id and c.attr = 3);
      

      请注意,此查询准确地说明了您的规范所说的内容:从item_table 中获取所有行,其中至少存在来自attr_table 的行,该行具有该行的 id 并且第一个 attr 指定和 em> 其中至少存在来自attr_table 的一行,该行具有该行的 id 和指定的第二个 attr。

      【讨论】:

        【解决方案4】:
        select distinct item_table.item from item_table, attr_table
        where item_table.id = attr_table.item_id
        and attr_table.attr = 1 and attr_table.attr = 3;
        

        基本上,它会进行您期望的匹配,并以大量行结束 - 但随后 distinct 关键字起作用,因此您将获得最小的唯一行集作为最终结果。

        (顺便说一句,我希望它更有效,但不要费心去弥补匹配行的完整列表)。

        【讨论】:

        • 实际上不起作用,因为没有“attr = 1 and attr = 2”为真的单行。
        • 我不明白。 “2”是错字吗?应该是“3”吗?
        【解决方案5】:

        这可能为时已晚,但我建议使用几个这样的连接:

        select i.item, b.item_id, c.item_id 
        from item_table i 
        join attr_table b on i.id=b.item_id and b.item_id=1
        join attr_table c on i.id=c.item_id and c.item_id=2
        

        我就是这样做的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-04-24
          • 2016-07-05
          • 1970-01-01
          • 1970-01-01
          • 2012-05-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多