如何正确查询规范化数据库

时间:2012-04-09 20:17:57

标签: mysql database

我正在重新设计一个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中的一列一样。这可能吗?

非常感谢任何帮助!

1 个答案:

答案 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好。)