我正在重新设计一个MySQL数据库,该数据库有一个包含大约1,500列的表,以及其他表。我们希望通过创建第二个表来规范化此表中的数据,该表将包含初始表中存在的每个列/行的记录。我们将这些表称为Master和MasterData。 Master将包含该表中所有记录所需的基本信息。 MasterData将包含与主表中的记录有关的一些附加数据的值。所以,让我们说Master会是这样的:
MasterID Property1 Property2
1 Yes No
2 No Yes
3 Yes Yes
4 No No
假设MasterData看起来像这样:
MasterID Property Value
1 Property3 Yes
1 Property4 No
3 Property3 No
4 Property7 Yes
到目前为止我?如何查询此数据,并且每个匹配的主行只返回一行,但包含所有相关的MasterData信息。我搜索并找到了几个例子,但是他们花了很长时间来执行我们的数据。我已经根据前面提到的一个巨大的表中的现有数据创建了一个测试MasterData表。这导致MasterData具有大约450万条记录,并且以下查询执行和超时的时间太长。
SELECT Property1, Property2, Master.MasterID,
GROUP_CONCAT(case when Property = "Property3" then Value end) as Property3,
GROUP_CONCAT(case when Property = "Property7" then Value end) as Property7
FROM Master LEFT JOIN MasterData USING (MasterID) GROUP BY MasterID
HAVING Property3='Yes' OR Property7='Yes';
或
Select * FROM Master AS M, MasterData AS MD1, MasterData AS MD2
WHERE M.MasterID=MD1.MasterID AND MD1.Property='Property3' AND MD1.Value='Yes'
AND M.MasterID=MD2.MasterID AND MD2.VAR='Property7' AND MD2.Value='Yes';
同样,我们的目标是能够在一行中检索MasterData中的所有数据,就好像它是Master中的一列一样。这可能吗?
非常感谢任何帮助!
答案 0 :(得分:2)
同样,我们的目标是能够在一行中检索MasterData中的所有数据,就好像它是Master中的一列一样。这可能吗?
在没有完全理解你的目标的情况下,严格来说,我会说出来可能可能。但在任何实际意义上都不太可能。即使是最好的情况(只有一两个属性),性能可能会非常糟糕;在可能的情况下(30到500个属性之间)你可能会完全关闭服务器。
规范化并不意味着“创建第二个表,该表将包含初始表中存在的每个列/行的记录”。它并不意味着甚至远程喜欢。但是可能标准化实际上会解决您的问题。 (根据我的经验,大多数数据库问题都是结构性的。)
您在此处提出的解决方案对于您未说明的问题效果不佳。要充分利用StackOverflow的专业知识,请说明您尝试解决的问题以及您尝试过的解决方案。
Wikipedia article about database normalization
如果你从这样的表开始。 。
create table master_data (
master_id integer not null,
property_name varchar(30) not null,
property_value boolean not null default true,
primary key (master_id, property_name)
);
insert into master_data values
(1, 'Property3', true),
(1, 'Property4', false),
(3, 'Property3', false),
(4, 'Property7', true);
。 。 。然后,您可以通过简单查询获取所有内容的所有属性。 (假设您的所有属性都是布尔值。)
select *
from master_data
order by master_id, property_name
--
1 Property3 t
1 Property4 f
3 Property3 f
4 Property7 t
应用程序代码可以非常简单地循环。并且您可能能够删除property_value为false的所有行。
此结构允许每件事物具有无限数量的属性。但是你的要求a)在一行中返回任意数量的属性,b)对应用程序代码进行最小的更改必须改变。没有办法解决这个问题。
如果您的表包含这些行。 。
insert into master_data values
(1, 'Property3', true),
(1, 'Property4', false),
(3, 'Property3', false),
(4, 'Property7', true),
(1, 'Property7', true);
这是获得一组符合条件的“事物”的一种方法,并将该组加入到主数据表中。
select md.*
from master_data md
inner join (select master_id
from master_data
where (
(property_name = 'Property3' and property_value = true) or
(property_name = 'Property7' and property_value = true)
)
group by master_id
having count(*) = 2 ) cd
on (md.master_id = cd.master_id)
对于它的价值,规范化仍然可能是您长期维护和性能的最佳选择。这种结构(上图)未规范化;对于大量数据,性能通常很差。 (带有可选hstore模块的PostgreSQL在这方面可能比MySQL好。)