如何从规范化的MySQL 5.7结构中检索与某些条件匹配的值

时间:2019-01-01 17:05:41

标签: mysql entity-attribute-value

我正在尝试通过替换SQL查询来规范我的MySQL 5.7数据shema和苦苦挣扎:

目前,有一个表格包含每篇文章的所有属性:

article_id | title | ref_id | dial_c_id

任务是检索与两个给定属性(ref_id和Dial_c_id)匹配的所有文章,并检索其所有其他属性。

只有一张桌子,这很简单:

SELECT *
    FROM test.articles_test
WHERE
    ref_id = '127712' 
    AND dial_c_id = 51 

现在,为了标准化,我创建了第二个表,该表存储了每篇文章的属性,并删除了表文章中的那些属性:

表1:

article_id | title 

表2:

article_id | attr_group | attribute
1            ref_id       51
1            dial_c_id    33
1            another      5
2 ..

我想检索所有文章详细信息,包括将这两个表shema与ref_id和Dial_c_id匹配的 ALL 属性。

这样:

SELECT 
     a.article_id,
     a.title, 
     attr.*
FROM test.articles_test a
INNER JOIN attributes attr ON a.article_id = attr.article_id
     AND ref_id = '127712' 
     AND dial_c_id = 51 

这怎么办?

1 个答案:

答案 0 :(得分:3)

您已使用实体-属性-值表记录您的属性​​。

这是归一化的相反

命名归一化规则,该规则可指导您将不同的属性放入同一列。 您不能,因为这不是规范化做法。

要用当前的EAV设计完成查询,您需要对结果进行透视,以便获得与原始表一样的东西。

SELECT * FROM (
    SELECT 
         a.article_id,
         a.title, 
         MAX(CASE attr_group WHEN 'ref_id' THEN attribute END) AS ref_id,
         MAX(CASE attr_group WHEN 'dial_c_id' THEN attribute END) AS dial_c_id
         -- ...others...
    FROM test.articles_test a
    INNER JOIN attributes attr ON a.article_id = attr.article_id
    GROUP BY a.article_id, a.title) AS pivot
WHERE pivot.ref_id = '127712' 
  AND pivot.dial_c_id = 51 

虽然上面的查询可以产生您想要的结果,但性能会很糟糕。它必须为子查询创建一个临时表,其中包含两个表中的所有数据,然后对临时表应用WHERE子句。

在原始表的每个列中,每个属性的确要更好。


我了解到您将来会尝试考虑许多属性。这是一个普遍的问题。

查看我的回答 How to design a product table for many kinds of product where each product has many parameters

但是您不应将其称为“规范化”,因为它不是。甚至没有非规范化。这是修饰语

您不能仅仅使用单词来描述您想要的任何东西,尤其是不能与单词的含义相反。我不能让空气从自行车轮胎中逸出,然后说:“我正在给它充气。”

您评论说,您正在尝试使数据库“可伸缩”。您还会误解“可扩展”一词的含义。通过使用EAV,您正在创建一种结构,其中所需的查询难以编写且执行效率低下,并且数据占用10倍的空间。 与可扩展性相反。

您的意思是您正在尝试创建一个可扩展的系统。这在SQL中实现很复杂,但是我在链接到的另一个Stack Overflow答案中描述了几种解决方案。您可能还会喜欢我的演示文稿Extensible Data Modeling with MySQL