1

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

Building(BuildingName), Floor(FloorName)

如果建筑物有 2 个名称(2 个语言 ID)和 5 个楼层,其中只有 3 个楼层具有两个语言 ID 的名称,我仍然希望有 10 个结果条目。楼层名称,当缺少语言 ID 时,它们会从不匹配的楼层 ID 中拉出(默认)。

4

1 回答 1

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
于 2012-11-29T18:53:22.097 回答