1

私は次の一般的なテーブル構造を持っています (私の不自然な例で米国中心の自動車メーカーを許してください):

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)
)

これらのテーブルの上にビューを作成して、すべての Fords と Chevys を取得し、ビューに生成された列を表示してメーカーを表示したいと考えています。私の最初の刺し傷はこれでした:

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)

しかし、それは私の口に悪い味を残し、私はパフォーマンスが心配です. すべての Fords と Chevys を個別の CTE 値で取得し、それらに対して和集合を実行したほうがよいでしょうか? 私は完全に間違った道を進んでいますか?また、Model 列 (および 2 つの子テーブルに共通するその他のいくつかの列) を含める必要もあります。これにより、明らかに、私のビューは巨大な一連のケース ステートメントになります。そのような状況を処理する「適切な」方法は何ですか?

編集:このスキーマは既に存在するため、基になるテーブルを変更できないことを追加する必要があると思いました。

4

1 に答える 1

1

まず、2 つのアプローチのそれぞれの長所と短所を見てみましょう。

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_Car:

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;

最初のものは単純な選択ですpeoplevw_Car1まったくクエリされません)。2 つ目はより複雑FordChevyなり、両方が照会されます。最初のアプローチの方が優れていると思うかもしれませんが、別のクエリを試してみましょう。

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

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

ここで、特に列にインデックスがある場合は、2番目の方が高速になりModelます。

=> sql fiddle demo - これらのクエリのクエリ プランを参照してください。

于 2013-09-06T16:49:35.260 に答える