【问题标题】:What is a SQL statement to select an item that has several attributes in an item/attribute list?什么是用于选择项目/属性列表中具有多个属性的项目的 SQL 语句?
【发布时间】:2010-10-29 23:43:20
【问题描述】:

假设我有一个表,其中列出了类似的项目和属性,

frog    green
cat     furry
frog    nice
cat     4 legs
frog    4 legs

我想从项目列中选择具有绿色和 4 条腿属性的独特对象。在这种情况下,我希望只取回青蛙对象。最有效的查询是什么?

【问题讨论】:

  • 项目/属性列表是什么意思? XML 属性?
  • 这么多人在这样一个模棱两可的不合逻辑的问题上提出了如此好的答案,祝你好运获得10分!
  • 它只是一个普通的sql表,如果它有帮助的话,该表称为Pets,它有两个字段项目和属性。我看不出这个问题有多么不合逻辑。
  • @Jason,你是说你的专栏里有“绿色”和“4 条腿”吗?
  • @Jason Christa 说“我想选择有 4 条腿并且是绿色的项目(青蛙),最有效的 SQL 语句是什么?” ——你不觉得这是一个模棱两可的不合逻辑的问题吗? ;-)

标签: sql relational-division sql-match-all


【解决方案1】:
select  item.name 
from    item 
where   item.attribute in ('4 legs', 'green') 
group by item.name 
having  count(distinct item.attribute) = 2

【讨论】:

  • +1 表示记得使用 DISTINCT。 OP 没有给出实际的表定义,所以我们不知道给定的项目/属性对是否必须是唯一的。
【解决方案2】:

最有效的方法是使用自联接:

SELECT * FROM attributes a1 
JOIN attributes a2 USING (item_name) -- e.g. frog
WHERE a1.value = 'green' AND a2.value = '4 legs';

有些人使用的另一种解决方案是使用 GROUP BY:

SELECT item_name FROM attributes
WHERE value IN ('4 legs', 'green')
GROUP BY item_name
HAVING COUNT(*) = 2;

但是 GROUP BY 解决方案可能不如 JOIN 高效,具体取决于您使用的 RDBMS 品牌。此外,随着表中容量的增加,一种方法可能会更好地扩展。

【讨论】:

  • 为什么说你的第一个解决方案更有效?
  • @Jason:我使用 MySQL 的经验是 GROUP BY 解决方案需要将中间结果写入临时表,这通常会降低性能。 JOIN 解决方案更好地使用索引。它甚至可以使用覆盖索引,并且从不接触表格。
  • 很高兴知道我正在使用 MySQL。我想知道如果我查询 12 个值会发生什么。
  • 您应该确保使用 EXPLAIN 语句分析优化计划,并学习如何读取输出。参考文档dev.mysql.com/doc/refman/5.1/en/explain.html
【解决方案3】:

select * from table where thing='frog'

没有什么比知道自己想要什么更好的了。

【讨论】:

  • 一开始我就想到了,但是我不确定 OP 是在问“只是那个”。 ;) 无论如何 +1。
  • 哈哈哈。我怀疑同时 100% 正确和 100% 错误
【解决方案4】:
select
    item, count(*)
from
    @temp
where
    attribute in ('4 legs','green')
group by
    item
having
    count(*) = 2 -- this "2" needs to be replaced with however many attributes you have

【讨论】:

    【解决方案5】:

    您也可以分别查询每个属性,然后将它们相交...

    /*
    -- create sample table...
    create table #temp1
        (item varchar(max),
        attrib varchar(max))
    
    -- populate sample table (SQL 08)...
    insert #temp1
    values ('frog', 'green'), ('cat', 'furry'), ('frog', 'nice'), ('cat', '4 legs'), ('frog', '4 legs')
    */
    
    
    SELECT  item
    FROM    #temp1
    WHERE   attrib = 'green'
    INTERSECT
    SELECT  item
    FROM    #temp1
    WHERE   attrib = '4 legs'
    

    【讨论】:

      【解决方案6】:

      创建两个表,一个是项目,一个是属性。
      项目可以是名称、intAttributeID,其中 intAttributeID 是对 Attributes 表的外键引用。这样,您就可以根据您关心的任何内容执行选择语句。

      【讨论】:

      • 将此表视为项目和属性之间的多对多关系之间的中间表。
      【解决方案7】:

      但也许这可以帮助你:

      SELECT * 
      FROM tbl t1
      INNER JOIN tbl t2 ON t1.Name = t2.Name
      WHERE t1.Attribute = 'green' AND t2.Attribute = '4 legs'
      

      【讨论】:

        【解决方案8】:

        很难,因为它不是标准化模型。这是一个周末。

        您正在过滤多个未连接的行,因此您必须依次提取每个属性,然后匹配项目。

        SELECT
           item
        FROM
            (SELECT
                item
            FROM
                Mytable
            WHERE
                attribute = '4 legs') k1
            JOIN
            (SELECT
                item
            FROM
                Mytable
            WHERE
                attribute = 'green') k2 ON k1.item = k2.item
        

        【讨论】:

        • 为什么说表格没有规范化?
        • 第一印象...我应该说“更难用于某些类型的查询”
        • KM 在评论 OP 时也一针见血
        【解决方案9】:

        如果可能,我会重新设计。这不是您能够同时有效地查询 12 个值的东西(它将需要 12 个连接)

        请阅读这篇维基百科文章 http://en.wikipedia.org/wiki/Entity-Attribute-Value_model#Downsides

        从未见过使用这种模型的数据库最终不会遇到严重的性能问题。这种设计对于非数据库的人来说看起来很优雅,但实际上通常是数据库设计不佳的标志。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-02-20
          • 2015-08-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多