如何从面向键值的表格布局中获得“传统”单行结果

时间:2011-04-07 10:39:12

标签: mysql select join key-value

我有一个设计为键值表的表,如

ID | key | value
1  | abc | value 1
2  | def | value 2
3  | geh | value 3

对于我们对数据的处理有很多好处。唯一的缺点是,我无法在这样的键值表上轻松排序。 什么是智能/通常的方式来获得结果集,所有键/值以传统方式“扁平化”,键显示为字段:

abc     | def     | geh
value 1 | value 2 | value 3

2 个答案:

答案 0 :(得分:1)

您只能使用存储过程执行此操作,并且在性能方面不会获得太多。

为了充分利用它,你可以在key-kvalue tabe上创建一个索引:

CREATE UNIQUE INDEX myindex ON keyvaluetable(key)

我假设您在UNIQUE字段中有key个值。如果没有,您当然可以删除该部分。

答案 1 :(得分:0)

你过度正常化,但你的例子不完整。如果您正在查看原始示例并尝试再添加一行,您将看到从表中不清楚值属于哪一行。您需要添加项目列:

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值进行假设,您就无法处理完全任意的数据类型(或者,如果您没有做出这样的假设,您可能会将您的应用内结构序列化并存储一个BLOB)。