Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 从相关子表创建视图_Sql_Sql Server_Sql Server 2008_Common Table Expression_Sql View - Fatal编程技术网

Sql 从相关子表创建视图

Sql 从相关子表创建视图,sql,sql-server,sql-server-2008,common-table-expression,sql-view,Sql,Sql Server,Sql Server 2008,Common Table Expression,Sql View,我有以下一般表格结构(请原谅我做作的例子中以美国为中心的汽车制造商): 我想在这些表的顶部创建一个视图,这样我就可以检索所有Ford和Chevy,并在视图中生成一个列,告诉我make。我的第一次尝试是: 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

我有以下一般表格结构(请原谅我做作的例子中以美国为中心的汽车制造商):

我想在这些表的顶部创建一个视图,这样我就可以检索所有Ford和Chevy,并在视图中生成一个列,告诉我make。我的第一次尝试是:

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列(以及两个子表共有的一些其他列),这显然会使我的视图变成一系列庞大的case语句。处理这种情况的“适当”方法是什么


编辑:我想我应该补充一点,这个模式已经存在,所以不可能更改基础表。

首先,让我们看看两种方法的优缺点:

create view vw_Car1
as
  SELECT 
      c.Id,
      case when f.FordId is not null then 'Ford' else 'Chevy' end as Maker,
      coalesce(f.Model, ch.Model) as Model
  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);

create view vw_Car2
as
  select FordId as id, 'Ford' as Maker, Model from Ford
  union all
  select ChevyId as id, 'Chevy' as Maker, Model from Chevy;
在联接中使用第一个更好,尤其是在不使用所有列的情况下。例如,假设您在使用
vw_汽车时有一个视图

create table people (name nvarchar(128), Carid int);

insert into people
select 'John', 1 union all
select 'Paul', 2;

create view vw_people1
as
select
    p.Name, c.Maker, c.Model
from people as p
   left outer join vw_Car1 as c on c.ID = p.CarID;

create view vw_people2
as
select
    p.Name, c.Maker, c.Model
from people as p
   left outer join vw_Car2 as c on c.ID = p.CarID;
现在,如果要执行简单选择:

select Name from vw_people1;

select Name from vw_people2;
第一个是从
人员
中进行简单选择(根本不会查询
vw_Car1
)。第二个将更加复杂-
Ford
Chevy
都将被查询。 您可能认为第一种方法更好,但让我们尝试另一个查询:

select *
from vw_people1
where Maker = 'Ford' and Model = 'Fiesta';

select *
from vw_people2
where Maker = 'Ford' and Model = 'Fiesta';
这里第二个会更快,尤其是当您在
Model
列上有索引时


-请参阅这些查询的查询计划。

首先,让我们尝试查看两种方法的优缺点:

create view vw_Car1
as
  SELECT 
      c.Id,
      case when f.FordId is not null then 'Ford' else 'Chevy' end as Maker,
      coalesce(f.Model, ch.Model) as Model
  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);

create view vw_Car2
as
  select FordId as id, 'Ford' as Maker, Model from Ford
  union all
  select ChevyId as id, 'Chevy' as Maker, Model from Chevy;
在联接中使用第一个更好,尤其是在不使用所有列的情况下。例如,假设您在使用
vw_汽车时有一个视图

create table people (name nvarchar(128), Carid int);

insert into people
select 'John', 1 union all
select 'Paul', 2;

create view vw_people1
as
select
    p.Name, c.Maker, c.Model
from people as p
   left outer join vw_Car1 as c on c.ID = p.CarID;

create view vw_people2
as
select
    p.Name, c.Maker, c.Model
from people as p
   left outer join vw_Car2 as c on c.ID = p.CarID;
现在,如果要执行简单选择:

select Name from vw_people1;

select Name from vw_people2;
第一个是从
人员
中进行简单选择(根本不会查询
vw_Car1
)。第二个将更加复杂-
Ford
Chevy
都将被查询。 您可能认为第一种方法更好,但让我们尝试另一个查询:

select *
from vw_people1
where Maker = 'Ford' and Model = 'Fiesta';

select *
from vw_people2
where Maker = 'Ford' and Model = 'Fiesta';
这里第二个会更快,尤其是当您在
Model
列上有索引时


-参见这些查询的查询计划。

是否可以使来自
Ford
FordId
等于1,以及来自
Chevy
ChevyId
等于1?:)哈,不,谢天谢地那是不可能的。每个Id值都是唯一的。您如何防止它?SQL Server optimizer是否知道这是不可能的?如果不是的话,那么如果你在联合中使用你的观点,你的工会可能会很慢。这是一个很好的问题。它的工作方式是,当创建福特时,首先将一个条目添加到Car表中,然后使用该添加中的SCOPE_IDENTITY()将其添加到福特或雪佛兰表中。这个系统已经有将近10年的历史了,正如你所知,它有许多值得怀疑的方面。关于减速的评论是非常有用的,因为这确实是不可发现的。是否有可能使来自
Ford
FordId
等于1,而来自
Chevy
ChevyId
等于1?:)哈,不,谢天谢地那是不可能的。每个Id值都是唯一的。您如何防止它?SQL Server optimizer是否知道这是不可能的?如果不是的话,那么如果你在联合中使用你的观点,你的工会可能会很慢。这是一个很好的问题。它的工作方式是,当创建福特时,首先将一个条目添加到Car表中,然后使用该添加中的SCOPE_IDENTITY()将其添加到福特或雪佛兰表中。这个系统已经有将近10年的历史了,正如你所知,它有许多值得怀疑的方面。关于减速的评论是非常有用的,因为这确实是不可发现的。谢谢你的详细回答。因此,如果我要根据视图中的某些where标准进行检索,我最好采用联合策略?@ledbutter这取决于您的查询,我认为没有什么灵丹妙药,尤其是在您无法更改模式的情况下。在您的例子中,您可以将模型移动到Cars表中,并使用连接策略(若您可以更改模式)。如果您采用联合策略,请注意使用表连接视图。谢谢您提供的详细答案。因此,如果我要根据视图中的某些where标准进行检索,我最好采用联合策略?@ledbutter这取决于您的查询,我认为没有什么灵丹妙药,尤其是在您无法更改模式的情况下。在您的例子中,您可以将模型移动到Cars表中,并使用连接策略(若您可以更改模式)。如果使用联合策略,请注意使用表连接视图。