【发布时间】:2015-02-24 09:44:36
【问题描述】:
这可能以前被问过,但这是一个如此复杂的话题,我很难理解它。所以想问问具体情况。
我有以下“CampaignCalls”表,例如:
ID | contactName | contactNumber
1 | Joe Bloggs | 123456789
2 | Simon Smith | 456987321
3 | Jane Doe | 852936414
此外,我还有用户定义的“自定义列”的一对多表,“CampaignCall_Fields”,例如:
ID | fieldName
1 | Company
2 | Alternative Number
3 | Address 1
4 | Address 2
以及定义自定义列(“CampaignCall_Field_values”)的每个对应值的相交表,例如:
CampaignCall_ID | field_ID | value
1 | 1 | ACME
1 | 2 | 789456123
1 | 3 | 123 Fake St
1 | 4 | London
2 | 1 | Initech
2 | 2 | 789456123
2 | 3 | 456 Fake St
2 | 4 | Paris
3 | 1 | Greendale
3 | 2 | 789456123
3 | 3 | 789 Fake St
3 | 4 | New York City
我有一个应用程序,它应该能够向用户显示所有行的报告,例如以下格式:
Name | Number | Company | Address 1 | Address 2
Joe Bloggs | 123456789 | ACME | 123 Fake St | London
Simon Smith | 456987321 | Initech | 456 Fake St | Paris
但我还想让用户能够在此示例中指定的任何列上创建过滤器,例如用户可以说“仅返回 Name = Joe Bloggs AND Company = ACME 的行”。
当前我这样做是通过从“CampaignCalls”表中提取所有数据(相应过滤),然后在 PHP 中遍历所有返回的行并从“CampaignCall_Field_values”中获取数据" 表(相应过滤),然后将数据旋转到主数组中(如果没有返回所有数据,我知道过滤器已“过滤掉”该行并从数组中删除该行)。
这是非常低效的,因为它需要很长时间并且为每一行打开不同的数据库连接。所以我想看看是否有办法减少数据库连接的数量和/或算法的复杂性。
我希望通过某种方式创建一些包含所有动态字段、具有适当索引等的数据库视图,然后针对该视图运行报告来理想地做到这一点。这似乎是最干净的方式,但不确定我将如何动态创建这样的视图。也不确定这对性能的影响。
有人可以就如何实施此解决方案或替代的更好的解决方案提供任何见解或意见吗?我一直在努力创造一个稳定、高效的解决方案,我不敢相信以前从未有人这样做过。提前致谢!
【问题讨论】:
-
这正是 EAV 模型被视为 SQL 反模式的原因。它当然在 RDBMS 设计中占有一席之地,但除非您有大量经常变化的属性,否则通常最好采用关系设计。我不会说太多,因为我不想引发争论,谷歌搜索 SQL EAV vs Relational 有 26,100 个结果,我想我不能说任何尚未说的内容。
-
好吧,我从来没有真正听说过 EAV...很高兴知道我在做什么有一个名字!我将如何将其重组为关系模式(不确定在这种情况下你所说的关系是什么意思)?或者对于单个评论来说太大了......
-
在关系模型中,您将没有表
CampaignCall_Field_values,而是在CampaignCalls上只有附加列。因此,您的表格已经处于您想要实现的结构中。就像我说的,网上有很多关于这个的文章,我没有什么可以补充的了。我建议选择一个并阅读每种方法的优缺点。 -
是的,这是有道理的。我快速阅读了您的链接和几篇文章,现在我已经开始思考了——只是想知道您对如何更改架构的看法。谢谢!
-
如果这正是您想要避免的那种问题,请随意忽略它 - 但由于这里的自定义值是动态的(用户控制的,它们的数量可变)这不构成改变现场制作中的模式?我一直认为这是一件坏事?
标签: php sql-server tsql where-clause