22

我已经对数据库中的表进行了规范化,并且为了对其进行非规范化,我从两个表中创建了一个视图。当我尝试在视图上创建聚集索引时,它不会让我这样做,因为视图是使用左外连接创建的。我使用了左连接,因为我希望空值显示在结果视图中,就像在之前的帖子中建议的那样。

关于一列一侧为空的连接问题

表结构和关系与上面链接中描述的非常相似。

我似乎在这里碰壁了,因为我无法将左连接转换为内连接,因为这将排除任何连接列上具有空值的所有记录。我的问题是:

  1. 为什么在外部或自连接上不允许索引?
  2. 这种未索引的视图是否有任何性能影响?
  3. 有人知道这个问题的任何解决方法吗?

我昨天刚刚完成了 SQL Server 课程,所以不知道如何继续。任何意见将不胜感激。干杯。

4

5 回答 5

14

这是一个替代方案。您想要一个不包含 B 的 A 的物化视图。这不是直接可用的......所以相反,物化两个视图。所有 A 之一和仅有 A 和 B 之一。然后,通过除 B 之外的 A 只得到 A 没有 B。这可以有效地完成:

创建两个物化视图(mA 和 mAB)(编辑:mA 可能只是基表)。mA 缺少 A 和 B 之间的连接(因此包含所有 A 的句点 [因此包含那些在 B 中没有匹配项的记录])。mAB 在 A 和 B 之间连接(因此仅包含 A 和 B [因此排除了 B 中没有匹配项的那些记录])。

要在 B 中获取所有没有匹配项的 A,请屏蔽那些匹配项:

with ids as (
  select matchId from mA with (index (pk_matchid), noexpand)
  except
  select matchId from mAB with (index (pk_matchid), noexpand)
)
select * from mA a join ids b on a.matchId = b.matchId;

这应该针对您的聚集索引产生一个左反半连接以获取 ids 和一个聚集索引寻求从您正在寻找的 mA 中获取数据。

本质上,您遇到的是基本规则,即 SQL 在处理存在的数据方面比处理不存在的数据要好得多。通过实现两个来源,您可以获得一些引人注目的基于集合的选项。您必须自己权衡这些观点的成本与这些收益。

于 2015-07-01T20:33:08.707 回答
10

这里有一个“解决方法” ,涉及NULL在连接中检查并在表中具有NULL 表示值

空值

INSERT INTO Father (Father_id, Father_name) values(-255,'No father')

加入

JOIN [dbo].[son] s on isnull(s.father_id, -255) = f.father_id
于 2011-06-25T09:38:53.460 回答
7

我不认为有一个好的解决方法。您可以做的是从视图创建一个真实的表并在其上设置索引。这可以通过在数据更新时定期调用的存储过程来完成。

Select * 
into <REAL_TABLE>
From <VIEW>

create CLUSTERED index <INDEX_THE_FIELD> on <REAL_TABLE>(<THE_FIELD>)

但如果数据不是每隔几秒更新一次,这只是一种值得注意的方法。

于 2012-11-26T14:20:35.440 回答
1

从逻辑上讲,您正在进行两个单独的查询。'A LEFT JOIN B' 只是 '(A JOIN B) UNION A' 的简写

第一个查询是表 A 内部连接到表 B。这将获得一个索引视图,因为这是完成所有繁重工作的地方。

第二个查询只是表 A,其中任何连接列都为空。创建一个生成与第一个查询相同的输出列并用空值填充它们的视图。

只需在返回它们之前合并两个结果。无需解决方法。

于 2013-02-05T18:16:05.007 回答
0

我将解决 1 的问题,但现在:

[2]。该视图的性能不会高于或低于对 udnerlying 表的等效查询。所有通常的建议都适用于覆盖索引,最好是连接列上的索引等。

[3]。没有真正的解决方法。一旦你深入研究它们,大多数索引视图的限制都是有很好的理由存在的。

一般来说,我只是创建视图,不再做任何事情,除非存在特定的性能问题。

一旦我在自己的脑海中重建了它,我将尝试为 1 添加一个答案。

于 2011-06-25T09:34:08.280 回答