Вы чрезмерно нормализуетесь, но ваш пример неполон.Если вы посмотрите на исходный пример и попытаетесь добавить еще одну строку, вы увидите, что из вашей таблицы неясно, к какой строке относится значение.Вам нужно добавить столбец элемента:
root@localhost [kris]> create table overnormal ( id serial, k varchar(20) not null, v varchar(20) not null);
Query OK, 0 rows affected (0.96 sec)
root@localhost [kris]> insert into overnormal values ( 1, 'abc', 'value 1'), (2, 'def', 'value 2'), (3, 'geh', 'value 3');
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0
root@localhost [kris]> select * from overnormal;
+----+-----+---------+
| id | k | v |
+----+-----+---------+
| 1 | abc | value 1 |
| 2 | def | value 2 |
| 3 | geh | value 3 |
+----+-----+---------+
3 rows in set (0.00 sec)
Давайте добавим столбец элемента:
root@localhost [kris]> alter table overnormal add column item integer unsigned not null;
Query OK, 3 rows affected (0.48 sec)
Records: 3 Duplicates: 0 Warnings: 0
root@localhost [kris]> update overnormal set item = 1;
Query OK, 3 rows affected (0.01 sec)
Rows matched: 3 Changed: 3 Warnings: 0
root@localhost [kris]> insert into overnormal values (4, 'abc', 'item 1/1', 2), (5, 'def', 'item 1/2', 2), (6, 'geh', 'item 1/3', 2);
Query OK, 3 rows affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
root@localhost [kris]> select * from overnormal;
+----+-----+----------+------+
| id | k | v | item |
+----+-----+----------+------+
| 1 | abc | value 1 | 1 |
| 2 | def | value 2 | 1 |
| 3 | geh | value 3 | 1 |
| 4 | abc | item 1/1 | 2 |
| 5 | def | item 1/2 | 2 |
| 6 | geh | item 1/3 | 2 |
+----+-----+----------+------+
6 rows in set (0.00 sec)
Вы можете преобразовать это в традиционную таблицу, используя соединение смерти:
root@localhost [kris]> select t1.item, t1.v as abc, t2.v as def, t3.v as geh
from overnormal as t1
join overnormal as t2
on t1.item = t2.item
and t1.k = 'abc'
and t2.k = 'def'
join overnormal as t3
on t1.item = t3.item
and t3.k = 'geh';
+------+----------+----------+----------+
| item | abc | def | geh |
+------+----------+----------+----------+
| 1 | value 1 | value 2 | value 3 |
| 2 | item 1/1 | item 1/2 | item 1/3 |
+------+----------+----------+----------+
2 rows in set (0.00 sec)
Вы можете отсортировать это обычным способом, используя предложение ORDER BY
.
Этот запрос не так уж и плох, но быстро снизит эффективность по мере того, как ваша таблица станет шире, даже с индексами, так какоптимизатор может запутаться в 9-10 таблицах за одно соединение.
Вам лучше использовать модель данных, которая ближе к 3-й нормальной форме и менее близка к DKNF, и да, это возможно и менеепроблема, чем вы думаете.В любом случае вы не можете обрабатывать совершенно произвольные типы данных, не делая предположений о допустимых значениях k-значений, которые в любом случае являются законными и требуются в вашем приложении (или, если вы не делаете таких предположений, вы также можете сериализовать структуру в приложении и сохранитьклякса).