MySQL:如何转换为EAV-第3部分?

xienkqul  于 2022-10-22  发布在  Mysql
关注(0)|答案(2)|浏览(147)

以前的相关文章:

给定表格:

TABLE: foo
===============================
| id | first_name | last_name |
===============================
| 1  | John       | Doe       |
| 2  | Jane       | Smith     |
| 3  | Ronald     | McDonald  |
-------------------------------

如何获取此表并将其转换为这些表(EAV实现)?:

TABLE: attribute
===========================
| id | fk_id | attribute  |
===========================
| 1  | 100   | first_name |
| 2  | 100   | last_name  |
---------------------------

TABLE: value
=========================================
| id | attribute_id | row_id | value    |
=========================================
| 1  | 1            | 1      | John     |
| 2  | 2            | 1      | Doe      |
| 3  | 1            | 2      | Jane     |
| 4  | 2            | 2      | Smith    |
| 5  | 1            | 3      | Ronald   |
| 6  | 2            | 3      | McDonald |
-----------------------------------------

笔记:

  • 属性。将提供fk_ id。
  • 价值。rowid用于标识值在原始表中如何分组为记录。

UPDATE:另外,我如何查询EAV表,以便使它再次看起来像表foo

v8wbuo2f

v8wbuo2f1#

我给@Phil填充EAV表的解决方案+1。一次插入一个属性。
下面是另一个逆转EAV转换的解决方案:

SELECT v.row_id AS id,
  MAX(IF(a.attribute='first_name',v.value,NULL)) AS first_name,
  MAX(IF(a.attribute='last_name',v.value,NULL)) AS last_name
FROM value v INNER JOIN attribute a
  ON v.attribute_id = a.id 
GROUP BY v.row_id

除了使用EAV之外,您已经将所有值放入了一个VARCHAR(255)或其他类型的列中,因此您丢失了有关原始列各自数据类型的信息。
如果不对属性名称进行硬编码(如@Phil所示的连接或如我所示的列),就真的无法“动态”完成这项工作。这与尝试编写动态数据透视查询基本上是相同的问题。
我在我的演讲Practical Object-Oriented Models in SQL和我的书SQL Antipatterns Volume 1: Avoiding the Pitfalls of Database Programming中写了更多关于EAV的内容。

eaf3rand

eaf3rand2#

我想你唯一的希望是使用foo表。如果没有ID,bar基本上是无用的。
尝试类似的方法(假设attribute.id是自动递增主键)

INSERT INTO `attribute` (`fk_id`, `attribute`)
VALUES (100, 'first_name');

INSERT INTO `value` (`attribute_id`, `row_id`, `value`)
SELECT LAST_INSERT_ID(), `id`, `first_name`
FROM `foo`;

INSERT INTO `attribute` (`fk_id`, `attribute`)
VALUES (100, 'last_name');

INSERT INTO `value` (`attribute_id`, `row_id`, `value`)
SELECT LAST_INSERT_ID(), `id`, `last_name`
FROM `foo`;

要重建foo表,请尝试以下操作

SELECT
    `fn`.`row_id` AS `id`,
    `fn`.`value` AS `first_name`,
    `ln`.`value` AS `last_name`
FROM `value` `fn`
INNER JOIN `attribute` `fn_a`
    ON `fn`.`attribute_id` = `fn_a`.`id`
    AND `fn_a`.`attribute` = 'first_name'
INNER JOIN `value` `ln`
    ON `fn`.`row_id` = `ln`.`row_id`
INNER JOIN `attribute` `ln_a`
    ON `ln`.`attribute_id` = `ln_a`.`id`
    AND `ln_a`.`attribute` = 'last_name'

呃,谢谢你提醒我为什么我讨厌这种模式

相关问题