Sql 多次连接两个表的备选方案

Sql 多次连接两个表的备选方案,sql,sql-server,join,sql-server-2008-r2,database-performance,Sql,Sql Server,Join,Sql Server 2008 R2,Database Performance,我的情况是,我必须多次加入一个表。其中大多数都需要左连接,因为有些值不可用。如何克服多次加入时查询性能差的问题 情景 桌子 [项目]:项目ID Guid,名称VARCHAR(MAX)。 [UDF]:EntityId Guid、EntityType字符(1)、UDFCode Guid、UDFName varchar(20) [UDFDetail]:UDFCode Guid,Description VARCHAR(最大值) 关系: [Project].ProjectId-[UDF].EntityId

我的情况是,我必须多次加入一个表。其中大多数都需要左连接,因为有些值不可用。如何克服多次加入时查询性能差的问题

情景 桌子 [项目]:项目ID Guid,名称VARCHAR(MAX)。
[UDF]:EntityId Guid、EntityType字符(1)、UDFCode Guid、UDFName varchar(20)
[UDFDetail]:UDFCode Guid,Description VARCHAR(最大值)

关系:
[Project].ProjectId-[UDF].EntityId
[UDFDetail].UDFCode-[UDF].UDFCode

UDF表根据UDFName列保存项目的自定义字段。但是,这些字段的值存储在UDFDetail的列描述中。 我有很多用于Project的自定义列,它们存储在UDF表中

例如,要获取项目的两个字段,请执行以下选择:

SELECT 
    p.Name ProjectName,
    ud1.Description Field1, 
    ud1.UDFCode Field1Id,
    ud2.Description Field2,
    ud2.UDFCode Field2Id
FROM
    Project p
    LEFT JOIN UDF u1 ON
        u1.EntityId = p.ProjectId AND u1.ItemName='Field1'
    LEFT JOIN UDFDetail ud1 ON
        ud1.UDFCode = u1.UDFCode
    LEFT JOIN UDF u2 ON
        u2.EntityId = p.ProjectId AND u2.ItemName='Field2'
    LEFT JOIN UDFDetail ud2 ON
        ud2.UDFCode = u2.UDFCode
问题 想象一下,上面的select与15个字段连接在一起。在我的查询中,我已经有大约10个字段,并且性能不是很好。运行大约需要20秒。我对这些表有很好的索引,所以看看执行计划,它只进行索引查找,而不进行任何查找。关于连接,它需要左连接,因为该特定项目可能不存在字段1

问题 有没有更有效的方法来检索数据?
在这样的架构中,如何查询一个项目的10个不同字段?

这对于注释来说太长了:

您可以选择
pivot
、显式聚合(使用条件函数)或
join
s。如果设置了适当的索引,
join
s可能是最快的方法

正确的索引应该是
UDF(EntityId、ItemName、UdfCode)

您可以通过运行以下查询来测试group by是否更快:

SELECT count(*)
FROM p LEFT JOIN
     UDF u1
     ON u1.EntityId = p.ProjectId LEFT JOIN
     UDFDetail ud1 
     ON ud1.UDFCode = u1.UDFCode;

如果运行得足够快,那么你可以通过方法考虑<代码>组。

你可以尝试这个非常奇怪的装置(它看起来不漂亮,但它只做一组外部连接)。中间结果是一个非常“宽”和“长”的数据集,然后我们可以通过聚合“压缩”数据集(例如,对于每个ProjectName,每个Field1列将有N个结果、N-1个null和1个非null结果,然后通过简单的最大聚合进行选择)[N是字段数]

select ProjectName, max(Field1) as Field1, max(Field1Id) as Field1Id, max(Field2) as Field2, max(Field2Id) as Field2Id
from (
    select
        p.Name as ProjectName,
        case when u.UDFName='Field1' then ud.Description else NULL end as Field1,
        case when u.UDFName='Field1' then ud.UDFCode else NULL end as Field1Id,
        case when u.UDFName='Field2' then ud.Description else NULL end as Field2,
        case when u.UDFName='Field2' then ud.UDFCode else NULL end as Field2Id
    from Project p
        left join UDF u on p.ProjectId=u.EntityId
        left join UDFDetail ud on u.UDFCode=ud.UDFCode
) tmp
group by ProjectName

实际上,可以在不使用内部查询的情况下重写查询,但这不会有太大的区别:),看看Gordon Linoff的建议和您的答案,也可能只需要20秒,但仍然值得一试。

将UDF保存为XML是否太晚了?这是一个更好的方法。是的,是的。因为db模式来自第三方。所以我不能修改主结构。我可以在模式中添加我自己的表,但我需要保持默认结构不变。这花了20秒。不仅仅是单独进行左连接。实际上几乎是一样的。可能做
pivot
更快。我怀疑它更好地利用索引进行优化。但是,当您有两个连接时,这可能没有什么区别。我的索引很好。对于每个数据检索操作,该操作都是索引查找。