【发布时间】:2013-09-10 19:37:48
【问题描述】:
我有以下通用表结构(请原谅在我设计的示例中以美国为中心的汽车制造商):
CREATE TABLE Car (
[Id] int PRIMARY KEY
)
CREATE TABLE Ford (
[FordId] int PRIMARY KEY, --also a foreign key on Car
[Model] nvarchar(max)
)
CREATE TABLE Chevy (
[ChevyId] int PRIMARY KEY, --also a foreign key on Car
[Model] nvarchar(max)
)
我想在这些表的顶部创建一个视图,以便我可以检索所有福特和雪佛兰,并在视图中生成一个告诉我品牌的列。我的第一个刺是这样的:
SELECT
c.CarId,
case when f.FordId is not null then 'Ford' else 'Chevy' end
FROM Car as c
LEFT JOIN Ford as f on c.Id = f.FordId
LEFT JOIN Chevy as ch on c.Id = ch.ChevyId
WHERE (f.FordId is not null or ch.ChevyId is not null)
但这在我的嘴里留下了不好的味道,我担心性能。以不同的 CTE 值检索所有福特和雪佛兰,然后对它们执行联合,我会更好吗?我完全走错了吗?我还需要包含 Model 列(以及两个子表共有的其他一些列),这显然会使我的视图变成一系列巨大的案例陈述。处理这种情况的“正确”方法是什么?
编辑:我想我应该补充一点,这个架构已经存在,所以改变基础表是不可能的。
【问题讨论】:
-
是否可以让来自
Ford的FordId等于1 和来自Chevy的ChevyId等于1? :) -
哈,不,谢天谢地,这是不可能的。每个 Id 值都是唯一的。
-
你如何预防呢? SQL Server 优化器是否知道这是不可能的?如果没有,那么如果您将在联接中使用您的视图,那么您的联合可能会很慢
-
这是一个很好的问题。它的工作方式是,在创建 Ford 时,首先将一个条目添加到 Car 表中,然后使用该添加中的 SCOPE_IDENTITY() 来添加到 Ford 或 Chevy 表中。如您所知,该系统已接近 10 年,并且有许多值得怀疑的方面。关于减速的评论,因为这确实是不可发现的,非常有用。
标签: sql sql-server sql-server-2008 common-table-expression sql-view