【问题标题】:I want to make a sql query to get distinct products data having attributes in separate table我想进行 sql 查询以获取具有单独表中的属性的不同产品数据
【发布时间】:2018-10-21 11:12:51
【问题描述】:

我有的桌子:

  1. 产品(ID、标题)

[1, '旧车'], [2, '新车'], [3, '未来车'])

  1. 属性(ID、名称)

[1, '品牌'], [2, '型号'], [3, '颜色']

  1. 属性值(attribute_id、product_id、值)

[1, 1, '丰田'], [1, 2, '本田'], [1, 3, '福特'], [1, 3, '红色'], [2, 3, '白色'], [3, 3, '红色']

我试过查询:

select p.*, a.name as attribute_name, av.value as attribute_value from attributes as a 
join attribute_values as av on a.id=av.attribute_id
join products as p on av.product_id=p.id
where
((a.name='brand' and av.value='toyota') or (a.name='color' and av.value='red'))

它给出匹配或查询条件的每一行。

例如:

  • [id:1, title:'旧车', attribute_name:'品牌', 属性值:'丰田']
  • [id:1, title:'旧车', attribute_name:'color', 属性值:'红色']
  • [id:3, title:'未来汽车', attribute_name:'color', 属性值:'红色']

在这里,找到的结果是:“旧车”和“未来车”,但我需要“旧车”而不是“未来车”。

这可以通过单个查询来完成吗?

【问题讨论】:

  • 你想要的结果到底是什么?
  • 我只是想确认您提到的记录是否正确。因为对于属性“模型”,您提到“新车”的“白色”。这是关于 Attribute_values 表
  • 顺便说一句,这并没有什么不同,但我们通常会将实体(产品)列放在 EAV 表的开头。
  • @Simone 是的,产品与属性的关系保存在 Attribute_values 表中
  • @Strawberry 我不明白你的意思。

标签: mysql sql


【解决方案1】:

假设这是正确的,我已将您的属性值表中的记录更改如下:

attribute_id  |   product_id   |   value
------------------------------------------
1         |       1        |   toyota
1         |       2        |   honda
1         |       3        |   ford
3         |       1        |   red
3         |       2        |   white
3         |       3        |   red

我已将您的查询修改如下:

select p.*, a.name as attribute_name, av.value as attribute_value from attributes as a 
    join attribute_values as av on a.id=av.attribute_id
    join products as p on av.product_id=p.id
    where
        (
            if(a.name='brand',av.value='toyota',0) 
      or if(a.name='color',av.value='red',0)
     ) 
GROUP BY p.id HAVING COUNT(av.attribute_id) =2

这里 “2” 应该是动态的,具体取决于您过滤的属性数量。由于在您的示例中您已使用 2 个属性进行过滤,因此我提到了 2

小提琴出现在:http://sqlfiddle.com/#!9/b6ff9/2

【讨论】:

    【解决方案2】:

    你可以试试这个查询。当记录与您的条件中的 1 个匹配时,原始查询输出 1 行。 从结果中,我们检查相同的product id 结果中是否有 2 条记录。如果是,则意味着 2 个条件(品牌 = Toyota & 颜色 = red)与相同的 product 匹配。

    SELECT id as product_id, count(attribute_name) as attribute_count FROM
    (
        select 
            p.*, 
            a.name as attribute_name, 
            av.value as attribute_value
    
        from products as p 
            join attribute_values as av
                on p.id = av.product_id
            join attributes as a 
                on a.id = av.attribute_id
    
        where
            (a.name='brand' and av.value='toyota')
            or (a.name='color' and av.value='red')
    
    ) a
    
    GROUP BY a.id
    HAVING (attribute_count = 2);
    

    用于测试的 SQL Fiddle 链接:http://sqlfiddle.com/#!9/ab857a/2

    编辑:

    另一方面,您也可以试试这个second approach。首先,我们执行 2 个单独的 subselect 以获得符合 2 个标准中的每一个的产品。然后我们JOIN子选择一起得到符合这两个条件的产品:

    SELECT
        a.*,
        b.attribute_2,
        b.value_2
    
    FROM
    (
        SELECT 
            p.*, 
            a.name as attribute_1, 
            av.value as value_1
        FROM
            products as p
            JOIN attribute_values as av 
                ON av.product_id = p.id
            JOIN attributes as a
                ON a.id = av.attribute_id
        WHERE
            a.name = 'brand'
            and av.value = 'toyota'
    ) a
    
    JOIN
    
    (
        SELECT 
            p.*, 
            a.name as attribute_2, 
            av.value as value_2
        FROM
            products as p
            JOIN attribute_values as av 
                ON av.product_id = p.id
            JOIN attributes as a
                ON a.id = av.attribute_id
        WHERE
            a.name = 'color'
            and av.value = 'red'
    ) b
    
    ON a.id = b.id
    

    此处的 SQL Fiddle 代码示例:http://sqlfiddle.com/#!9/8b836d/1

    【讨论】:

    • 这不是我的反对意见,但那些确实需要留下来加入
    • @Strawberry,因为他正在寻找要匹配的两个条件(品牌丰田和红色),所以它必须是 JOIN,而不是 left join。除非我在这里遗漏了什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-21
    • 1970-01-01
    • 2020-02-24
    • 2017-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多