为缺少的关系创建具有备用/默认值的视图

时间:2012-11-29 18:20:05

标签: sql sql-server tsql views

在具有多个一对多关系对象的设置中,每个关系都使用来自单独表的名称属性。例如

Building(BuildingName), Floor(FloorName)

如果建筑物有2个名称(2个语言ID)和5个楼层,其中只有3个楼层有两个语言ID的名称,我仍然希望有10个结果条目。楼层名称,当语言ID丢失时丢失,从非匹配的楼层ID中提取(默认)。

1 个答案:

答案 0 :(得分:1)

这是否适合您所追求的目标?

此处可运行的示例:http://sqlfiddle.com/#!3/894e9/4

if object_id('[FloorName]') is not null drop table [FloorName]
if object_id('[BuildingName]') is not null drop table [BuildingName]
if object_id('[Floor]') is not null drop table [Floor]
if object_id('[Building]') is not null drop table [Building]
if object_id('[Language]') is not null drop table [Language]

create table [Language]
(
    Id bigint not null identity(1,1) primary key clustered
    , code nvarchar(5)
)
create table [Building]
(
    Id bigint not null identity(1,1) primary key clustered
    , something nvarchar(64)
)
create table [Floor]
(
    Id bigint not null identity(1,1) primary key clustered
    , BuildingId bigint foreign key references [Building](Id)
    , something nvarchar(64)
)
create table [BuildingName]
(
    Id bigint not null identity(1,1) primary key clustered
    , BuildingId bigint foreign key references [Building](Id)
    , LanguageId bigint foreign key references [Language](Id)
    , name nvarchar(64)
)
create table [FloorName]
(
    Id bigint not null identity(1,1) primary key clustered
    , FloorId bigint foreign key references [Floor](Id)
    , LanguageId bigint foreign key references [Language](Id)
    , name nvarchar(64)
)

insert [Language]
      select 'en-us'
union select 'en-gb'
union select 'fr'

insert [Building]
      select 'B1'
union select 'B2'

insert [Floor]
      select 1, 'F1.1'
union select 1, 'F1.2'
union select 1, 'F1.3'
union select 1, 'F1.4'
union select 1, 'F1.5'
union select 2, 'F2.1'
union select 2, 'F2.2'
union select 2, 'F2.3'
union select 2, 'F2.4'
union select 2, 'F2.5'

insert BuildingName
select b.Id
, l.id
, 'BuildingName :: ' + b.something + ' ' + l.code
from [Building] b
cross join [Language] l
where l.code in ('en-us', 'fr')

insert FloorName
select f.Id
, l.Id
, 'FloorName :: ' + f.something + ' ' + l.code
from [Floor] f
cross join [Language] l
where f.something in ( 'F1.1', 'F1.2', 'F2.1')
and l.code in ('en-us', 'fr')

insert FloorName
select  f.Id
, l.Id
, 'FloorName :: ' + f.something + ' ' + l.code
from [Floor] f
cross join [Language] l
where f.something not in ( 'F1.1', 'F1.2', 'F2.1')
and l.code in ('en-us')


declare @defaultLanguageId bigint
select @defaultLanguageId = id from [Language] where code = 'en-us' --default language is US English

select b.Id
, b.something
, bn.name
, isnull(bfn.name, bfnDefault.name)
, bl.code BuildingLanguage
from [Building] b
inner join [BuildingName] bn
    on bn.BuildingId = b.Id
inner join [Language] bl
    on bl.Id = bn.LanguageId
inner join [Floor] bf
    on bf.BuildingId = b.Id
left outer join [FloorName] bfn
    on bfn.FloorId = bf.Id
    and bfn.LanguageId = bl.Id
left outer join [Language] bfl
    on bfl.Id = bfn.LanguageId
left outer join [FloorName] bfnDefault
    on bfnDefault.FloorId = bf.Id
    and bfnDefault.LanguageId = @defaultLanguageId

修改

此版本默认使用任何语言:

select b.Id
, b.something
, bn.name
, isnull(bfn.name, (select top 1 name from [FloorName] x where x.FloorId=bf.Id))
, bl.code BuildingLanguage
from [Building] b
inner join [BuildingName] bn
    on bn.BuildingId = b.Id
inner join [Language] bl
    on bl.Id = bn.LanguageId
inner join [Floor] bf
    on bf.BuildingId = b.Id
left outer join [FloorName] bfn
    on bfn.FloorId = bf.Id
    and bfn.LanguageId = bl.Id
left outer join [Language] bfl
    on bfl.Id = bfn.LanguageId