在动态表结构中连接字段的最有效方法

时间:2012-03-28 02:37:12

标签: sql tsql

我们有三个表存储文档信息,我称之为表A,B和C.表A存储所述文档的主要字段(例如文件名和大小以及其他一般信息)。为了动态添加新字段,我们使用表B来存储新字段及其数据类型的列表(由枚举确定),并使用表C来存储这些字段的值。

Table A
ID   - PK int
FieldX...
FieldY...
FieldZ...

Table B
Id   - PK int
Name - nvarchar(max)
Type - int

Table C
Id    - PK int
AId   - FK to table A int
BId   - FK to table B int
Value - nvarchar(max)

我们想要尽可能高效地做的是将表C中的值作为表A中查询中的附加列。现在,这是我为表B中的每个额外字段执行此操作的方法。 / p>

select (select c.value 
        from B b, C c
        where c.AId = a.Id 
        and c.Bid = b.Id
        and b.Name = 'Dynamic Field Name') As 'Dynamic Field Name'
From A a

我们有一个表A填充了36000行的数据库。对于添加到查询的每个其他动态字段,它会在完成查询的总时间上添加大约4秒,使包含10个动态字段的查询至少需要40秒。实际上,我们希望任何查询都在10以下完成。有没有办法更有效地写这个?

2 个答案:

答案 0 :(得分:0)

首先,您的查询可能会给您错误,因为您没有将C.(A + B)定义为唯一。如果C中每个A+B组合有多个值,则会导致子查询失败并显示

Msg 512, Level 16, State 1, Line 1
Subquery returned more than 1 value.

假设它是唯一的,那么你应该安全地将它们连接在一起以便使用基于SET的操作。

select a.*,
       c1.value [Dynamic Field Name 1],
       c2.value [Dynamic Field Name 2]
From A a
JOIN B b1 on b1.Name = 'Dynamic Field Name1'
LEFT JOIN C c1 on c1.AId = a.Id and c.Bid = b1.Id
JOIN B b2 on b2.Name = 'Dynamic Field Name2'
LEFT JOIN C c2 on c2.AId = a.Id and c2.Bid = b2.Id

在SELECT级别使用子查询会强制每条记录,并且每个动态字段都以mini-select =非常慢的速度执行。

答案 1 :(得分:0)

也许像这样的查询也会起作用:

select a.id
      ,MAX(CASE WHEN b.Name = 'Dynamic Field Name' THEN c.value END) As Dynamic_Field_Name
      ,MAX(CASE WHEN b.Name = 'Dynamic Field Name 2' THEN c.value END) As Dynamic_Field_Name2
  from A a,  B b, C c
  where c.AId = a.Id 
    and c.Bid = b.Id
    and b.Name IN ('Dynamic Field Name', 'Dynamic Field Name 2')
  group by a.id

同样的想法,你只想在表中进行一次传递,而不是每行查找一次。聚合是将稀疏矩阵压缩成单行(即,一行中只有一个动态字段值,每行具有一个具有值的不同列)。不知道它会如何表现。