【问题标题】:SQL view, performance and count from one-to-many relationship一对多关系的SQL视图、性能和计数
【发布时间】:2011-09-26 18:58:37
【问题描述】:

我需要一些帮助来为我的一堆表构建基本的 SQL-VIEW。这是一个快速概述

  • 我有一个 ClaimDetail 表,它有一些查找字段,如 StatusID、BrandID、SalespersonID 等。
  • 与往常一样,查找字段映射到 MasterStatus、MasterBrand 等主表... {Structure: ID, Title}
  • 还有另外两个表 Comments 和 Files。一个声明可以有多个评论和多个文件。
  • 我需要显示一个仪表板,该仪表板将是一个索赔列表。我需要显示主表中的标题以及 cmets 和文件的数量。

现在,我有此仪表板的两个视图,一个用于客户类型的用户,仅限于某些细节,另一个是用于内部用户的详细视图。您可以说客户视图是内部视图的子集。

我看到两个选项 -

  1. 选项#1:创建一个单一的 vw_Internal 视图和 使用它来获取数据 用户。
  2. 选项#2:我创建了一个 vw_Customer 其中只有那些领域 客户需要,并且 然后我创建一个 vw_Internal 就像:vw_Customer INNER JOIN 主表。简而言之,我将扩展 要包含的基本 vw_Customer 更多字段。

从速度和性能的角度来看,选项#2 是否有意义?选项#1 很简单,但考虑到大量记录,我想确保客户不必为那些不会包含在他们的仪表板中的额外查找等待更长的时间。

最后,有没有办法实现我提到的最后一个功能?这就是获取与 ClaimDetail 表具有一对多关系的 Comments 和 Files 的计数。我只需要计数或至少一个布尔字段,说明索赔是否有任何评论(文件相同)-如果计数 = 0,则为假。我也担心此功能对性能的影响.

提前致谢。

【问题讨论】:

    标签: sql-server performance join outer-join sql-view


    【解决方案1】:

    关于视图定义,我将构建两个视图,并将它们分开——两个视图都不会引用另一个视图。这将允许您独立优化查询,并避免您在视图分层视图时遇到的任何问题;层数过多会使数据库管理、维护和重构变得特别具有挑战性。

    对于数据聚合,常见的策略包括以下几种。比较、对比、测试和推断,看看什么最适合您的环境:

    子查询

    SELECT mt.Id, st1.HowMany, st2.HowManyOther, <etc>
     from MainTable mt
      inner join (select Id, count(*) HowMany
                   from SubTable1
                   group by Id) st1
       on st1.Id = mt.Id
      inner join (select Id, count(*) HowMany
                   from SubTable2
                   group by Id) st2
       on st2.Id = mt.Id
    

    相当简单,尽管子查询可能会有点昂贵,即使有正确的索引。

    计数(不同的 xx)

    SELECT mt.Id, count(distinct st1.UniqueKey) HowMany, count(distinct st2.UniqueKey) HowManyOther, <etc>
     from MainTable mt
      inner join SubTable1 st1
       on st1.Id = mt.Id
      inner join SubTable2
       on st2.Id = mt.Id
    

    这需要“子表”中的单个唯一列,如果您必须处理外连接或 NULL,则会变得混乱。


    添加


    首先,在上述任一查询中将内连接替换为(左)外连接都会从子表中产生 0+ 个计数,只要您确保计数是在“右”表上完成的(因为 NULL不要被统计)。要确定哪个在您的环境中表现最好,您必须编写和测试这两个查询。我猜是第二个,因为第一个需要对子查询的表进行表扫描,而第二个执行连接,因此可能会优化得更好,但是 SQL 查询优化器比我更聪明(因为它知道您的索引并具有分布直方图你的数据),所以你想看看它会产生什么。

    关于“分层视图”,如果我遵循正确的逻辑,我建议将内部视图构建为复杂/综合查询(所有连接、所有相关列),然后构建客户视图希望如此简单

    SELECT <customerOnlyColumns>
     from vw_Internal
    

    【讨论】:

    • 谢谢。我保留一个主视图和一个包装器视图的目的是我不必复制逻辑两次。你能告诉我从性能的角度来看有什么不同吗?Opt#1 还是 Opt#2?
    • 关于子表计数,我需要遵循 LEFT OUTER JOIN 模式的内容,因为可能有 >= 0 个子记录(而不是 >= 1)。我希望您的两个查询都能实现。
    • 我会接受凯利清晰描述的答案,因为没有其他人出现:-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 2013-09-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多