在具有多个一对多关系对象的设置中,每个关系都使用来自单独表的名称属性。例如
Building(BuildingName), Floor(FloorName)
如果建筑物有2个名称(2个语言ID)和5个楼层,其中只有3个楼层有两个语言ID的名称,我仍然希望有10个结果条目。楼层名称,当语言ID丢失时丢失,从非匹配的楼层ID中提取(默认)。
答案 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