如何在MySQL中使用proprety/value表

如何在MySQL中使用proprety/value表,mysql,Mysql,我继承了一个mysql数据库,它有一个包含如下列的表: 1,first_name,Jane 1,last_name,Doe 1,age,10 1,color,red 2,first_name,Mike 2,last_name,Smith 2,age,20 2,color,blue 3,first_name,John 3,last_name,Doe 3,age,20 3,color,red ... SELECT object_id, IF(property='first_name',value,

我继承了一个mysql数据库,它有一个包含如下列的表:

1,first_name,Jane
1,last_name,Doe
1,age,10
1,color,red
2,first_name,Mike
2,last_name,Smith
2,age,20
2,color,blue
3,first_name,John
3,last_name,Doe
3,age,20
3,color,red
...
SELECT object_id, IF(property='first_name',value,NULL) AS first_name, IF(property='last_name',value,NULL) AS last_name, IF(property='age',value,NULL) AS age FROM table GROUP BY object_id;
对象id、属性、值

它包含如下数据:

1,first_name,Jane
1,last_name,Doe
1,age,10
1,color,red
2,first_name,Mike
2,last_name,Smith
2,age,20
2,color,blue
3,first_name,John
3,last_name,Doe
3,age,20
3,color,red
...
SELECT object_id, IF(property='first_name',value,NULL) AS first_name, IF(property='last_name',value,NULL) AS last_name, IF(property='age',value,NULL) AS age FROM table GROUP BY object_id;
基本上我想做的是把这张桌子当作一张普通的桌子。我如何获得一个20岁的人的身份证号码(或所有财产),按姓和名排序?到目前为止,我已经:

SELECT object_id FROM table WHERE property = 'age' AND value = '20'
union
SELECT object_id FROM table WHERE property = 'color' AND value = 'red'
但我不知道如何对数据进行排序


谢谢

正如您所发现的,属性/值表是一个非常糟糕的主意。它们打破了SQL希望数据显示的方式,无法正确索引,等等。对于那些不想维护数据库的人来说,它们是一个草率的解决方案(或者那些有意为用户提供“可扩展性”,但没有考虑所有问题的人)

如果这是一种选择,我强烈建议将这些乱七八糟的东西转换成普通的桌子。这可能需要一段时间,但它是值得的


至于您的具体问题,我不确定mysql是否支持
pivot
。如果是这样的话,那就好了“旋转”您的结果集到一个水平表中,然后您可以按预期顺序进行排序。如果没有,您可以用大量的
case
语句和一些聚合来拼凑一个假轴,将所有行折叠在一起。。。但是它是草率的、缓慢的。

在EAV模型中重建行的困难正是您所看到的

您必须将数据从行转到列,才能找到“对象”,然后对其进行查询

通常,枢轴可以通过以下方式完成:

SELECT object_id
    ,MAX(CASE WHEN property = 'age' THEN value ELSE NULL END) AS age
    ,MAX(CASE WHEN property = 'color' THEN value ELSE NULL END) AS color
-- ...
FROM EAVTABLE
GROUP BY object_id
然后:


除非由于其他原因(例如官僚主义法令)阻止您这样做,否则我会首先规范化该表,至少如果“对象”之间的属性名称一致的话。这样做几乎肯定意味着必须重写现有的查询,但您继续编写的任何查询实际上都是正常的,任何跟随您的人都至少有机会维护它们(并编写新的查询)

也就是说,如果你完全被你所拥有的东西所束缚,你可以像这样在飞行中伪造一个数据透视表:

1,first_name,Jane
1,last_name,Doe
1,age,10
1,color,red
2,first_name,Mike
2,last_name,Smith
2,age,20
2,color,blue
3,first_name,John
3,last_name,Doe
3,age,20
3,color,red
...
SELECT object_id, IF(property='first_name',value,NULL) AS first_name, IF(property='last_name',value,NULL) AS last_name, IF(property='age',value,NULL) AS age FROM table GROUP BY object_id;
然后在子选择中使用该选项。但正如唐尼所说,这将非常缓慢。我想您可以在子选择中使用
,缩减
对象id
的集合,但实际上,您不可能从这样的表中获得与您想要的查询相当的性能


(另一件可怕的事——像“age”这样的数值被存储为varchars?!?

您希望特定id的所有属性都在不同的列中(在这种情况下:属性的数量是有限的,它们是什么),还是仅仅在一个字符串中?不幸的是,MySQL中没有pivot。我同意这是一个糟糕的数据库模型,但这是我必须处理的问题。谢谢你的意见…谢谢你的回答。。。我完全同意这张桌子有多糟糕,但我有点被它卡住了。。。没有那么多数据,所以应该不会太糟糕。