【问题标题】:MySQL, SQL query over several rowsMySQL,SQL查询多行
【发布时间】:2016-08-31 10:37:51
【问题描述】:

我有一个名为clothing_properties 的表,其中一些行如下所示:

id  product_id  property_name   property
55  189000      color           blue
56  189000      type            tshirt
57  189000      size            medium
58  189001      color           red
59  189001      type            tshirt
60  189001      size            medium

我想创建一个 SQL 查询,该查询能够从用户搜索的内容中选择正确的 product_id。因此,如果用户搜索 tshirt 和 medium,我希望 SQL 查询返回:189000 和 189001。如果用户搜索 tshirt 和 blue,我只希望返回此产品 ID:189000。如何创建 SQL 查询这样做?

【问题讨论】:

  • 我认为您的表格结构不正确。每个属性名称应该是包含相应属性条目的不同字段。

标签: php mysql key-value key-value-store


【解决方案1】:

这种表通常称为键/值存储。这是处理可扩展属性列表的有效方法,但使用起来可能有点麻烦。

这样的查询将为您提供product_id 值,按照它们与您的条件列表的匹配程度排列,最佳匹配优先。 (http://sqlfiddle.com/#!9/7870b5/2/0)

select count(*) matches, product_id
  from prop
 where property in ('tshirt','medium')
 group by product_id
 order by 1 desc 

不过,此查询不知道大小、颜色和类型之间的区别。

如果您想精确匹配尺寸、颜色等,它会变得有点复杂。您需要从一个查询您的键/值属性表开始——将行转换为列。 (http://sqlfiddle.com/#!9/7870b5/3/0)

select id.product_id, 
       color.property color,
       type.property type,
       size.property size
 from (select distinct product_id from prop) id
 left join prop color on id.product_id = color.product_id and color.property_name = 'color'
 left join prop type on id.product_id = type.product_id and type.property_name = 'type'
 left join prop size on id.product_id = size.product_id and size.property_name = 'size'

然后您需要将其视为虚拟表并对其进行查询,可能是这样。 (http://sqlfiddle.com/#!9/7870b5/4/0)

select *
  from (

        select id.product_id, 
               color.property color,
               type.property type,
               size.property size
         from (select distinct product_id from prop) id
         left join prop color on id.product_id = color.product_id and color.property_name = 'color'
         left join prop type on id.product_id = type.product_id and type.property_name = 'type'
         left join prop size on id.product_id = size.product_id and size.property_name = 'size'
         ) allprops
 where size='medium' and color = 'blue'

许多开发人员和 dbas 会创建一个类似于 allprops 的视图,以简化此操作。

【讨论】:

    【解决方案2】:

    您想完全忽略property_name 列吗?

    SELECT DISTINCT product_id
    FROM   clothes_properties
    WHERE  property IN ('tshirt', 'medium');
    
    SELECT DISTINCT product_id
    FROM   clothes_properties
    WHERE  property IN ('tshirt', 'blue');
    

    【讨论】:

      【解决方案3】:

      我会使用 GROUP BYHAVING 来做到这一点:

      select product_id
      from clothes_properties
      where property_type = 'type' and property = 'tshirt' or
            property_type = 'size' and property = 'medium'
      group by product_id
      having count(distinct property_type) = 2;
      

      注意:如果给定产品没有重复的属性类型,则不需要 distinct

      如果你想要一些通用的东西,你可以使用:

      select product_id
      from clothes_properties
      where property_type = 'type' and (property = $type or $type = '') or
            property_type = 'size' and (property = $size or $size = '') or
            property_type = 'color' and (property = $color or $color = '')
      group by product_id
      having count(distinct property_type) = (($type <> '') + ($size <> '') + ($color <> ''));
      

      【讨论】:

      • 我尝试了您的第一个示例,并且在小桌子上进行测试时效果很好。现在将在更大的桌子上尝试。非常感谢您的帮助!
      【解决方案4】:

      试试这个

      SELECT DISTINCT(product_id) FROM clothes_properties WHERE property IN ('tshirt','medium') group by product_id having count (distinct property) = 2

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-21
        • 2012-12-01
        • 1970-01-01
        • 2022-01-19
        • 1970-01-01
        相关资源
        最近更新 更多