SQL flattening&动态查询问题

时间:2009-08-13 19:05:03

标签: sql dynamic entity-attribute-value flatten

首先,我不确定这是处理此问题的最佳方法......完全接受替代解决方案。

其次,我觉得我错过了显而易见的......但是我仍然想念它,所以不要自豪地问!

更新:.NET 3.5环境w / SQL 2005,所以像动态linq这样的东西是可能的,虽然我总是倾向于认为任何类型的动态(构建在线)查询都是笨重的。 PITA维持。

UPDATE 2 :响应northpole,伪代码/写入字逻辑/ sql / linq / C#都可以接受(!)...更多的是一个名义上“什么是好方法”而不是我需要代码的问题。

给出一张“鞋子”表,如下所示:

  ShoeID   PropertyName    PropertyValue
  1        COLOR           RED   
  2        COLOR           RED   
  2        SIZE            11
  3        COLOR           RED   
  3        SIZE            11   
  3        MANUFACTURER    GUCCI

我需要一种方法来查询鞋子

COLOR = RED返回

  1
  2
  3

COLOR = RED,SIZE = 11返回

  2
  3

COLOR = RED和SIZE = 11,MANUFACTURER = GUCCI返回

  3

在设计时,我知道可能有多少不同的属性,也不知道可能有多少查询参数......

希望这是有道理的......如果没有,请相应评论,我会再试一次。

3 个答案:

答案 0 :(得分:1)

因此,这是否是最佳方法取决于许多事情。例如,您是否需要支持可能具有不同(不兼容)属性的不同类别的实体(例如鞋子与礼服)?或者你所拥有的实体估计数量是多少(对于10K而言效果合理的东西不适用于100M)?或者您需要多长时间处理此类查询以及它们需要执行的程度?

两个最常见的思想流派是EAV model,它或多或少是你所拥有的column-based approach,你的实体的属性(颜色,大小等等)都被映射到一个单独的专栏。每个都有其优点和缺点,其中最大的是前者的灵活性/性能以及动态改变后者的表结构的必要性。

如果您使用现有模型,我建议您将属性名称移到单独的表中,并更改“鞋子”表以使FK到该表。然后,您可以在(property_idshoe_id)上创建索引并生成查询,如下所示:

SELECT shoe_id FROM shoes S_1 [, shoes S_2, ..., shoes S_X]
 WHERE S_1.property_id = 3 /* FK for 'color' */
  /* the following 3 lines will be repeated for each 'property' you need to query on */
   AND S_X.property_id = 4 /* FK for 'size' */
   AND S_X.shoe_id = S_1.shoe_id
   AND S_X.property_value = 'RED'
如果您的属性分布或多或少均匀,而且鞋子数量不多,那么

应该合理地执行

答案 1 :(得分:0)

动态sql会帮助你。类似的东西:

ALTER PROCEDURE [dbo].[sp_GetFilteredRecords]
(
...
@ConditionList nvarchar(MAX) = null
)
AS
BEGIN
  DECLARE @sql        nvarchar(MAX), 
          @paramlist  nvarchar(MAX)

  SELECT @sql = 'select ... '
  ...
  SELECT @sql = @sql + ' where 1=1 '
  ...
  SELECT @sql = @sql + ' ' + @ConditionList + ' '


  SELECT @paramlist = ...

  EXEC sp_executesql @sql, @paramlist

当然,由于工具可能略有不同。

鲍里斯。

答案 2 :(得分:0)

如果我理解正确,您希望能够创建一个查询,该查询可能具有基于任何数量的字段的标准,这些字段在前面是未知的。那太难了......

虽然大多数RDBMS都提供某种“动态SQL”功能,但这些方法往往使用起来很麻烦,或者速度很慢,或者两者兼而有之。

当然,您也可以在客户端代码中将SQL语句连接在一起,无论是C#,Java,PHP还是其他任何东西 - 但这又会变得很麻烦,容易发生SQL注入攻击,而且通常比较笨拙。

此外,如果您的查询与另一个请求不同,则RDBMS将无法缓存您的任何查询计划,并且获得正确的索引以获得良好的查询性能将充其量是挑战,不可能最糟糕的。

因此,虽然我完全理解了这个要求(并且几乎每天都必须自己解决这个问题),但实际上它并不适用。我宁愿尝试识别最常用的搜索及其标准,并确保这些搜索工作正常并且速度很快。限制用户的灵活性,以实现良好的查询性能。一个经典的权衡 - 你可以完全灵活,但是你的表现很糟糕,或者你可以让你的频繁查询运行得很快 - 但是会失去一些灵活性。

在一个可能获得某些东西的领域是在文本字段中搜索自由文本时 - 像SQL Server这样的RDBMS支持全文搜索的概念,这为您提供了一些灵活性和良好的性能。如果你有很多文本字段,请检查一下。

马克