Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/docker/9.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 server 取消SQL Server表的规范化_Sql Server_Denormalization - Fatal编程技术网

Sql server 取消SQL Server表的规范化

Sql server 取消SQL Server表的规范化,sql-server,denormalization,Sql Server,Denormalization,我有两个标准化的SQL Server 2008表,一个用于名称,另一个用于电子邮件: create table Name (NameId int, Name varchar(50)) create table Email (NameId int, Email varchar(50)) go insert into Name values (1, 'JOHN SMITH') insert into Name values (2, 'MARY SMITH') insert into Name va

我有两个标准化的SQL Server 2008表,一个用于名称,另一个用于电子邮件:

create table Name (NameId int, Name varchar(50))
create table Email (NameId int, Email varchar(50))
go

insert into Name values (1, 'JOHN SMITH')
insert into Name values (2, 'MARY SMITH')
insert into Name values (3, 'PHILL TAYLOR')
go

insert into Email values (1, 'john@hotmail.com')
insert into Email values (1, 'john@gmail.com')
insert into Email values (1, 'john.smith@hotmail.com')
insert into Email values (2, 'mary@hotmail.com')
insert into Email values (3, 'phill@hotmail.com')
insert into Email values (3, 'phill@gmail.com')
insert into Email values (3, 'taylor.phill@hotmail.com')
insert into Email values (3, 'taylor.phill@gmail.com')
go
当我加入这些表时,我有几行,其中一行只有一封电子邮件:

Select name, email
from Name inner join Email on name.NameId=email.NameId


NAME            EMAIL
-------------   --------------------------
JOHN SMITH      john@hotmail.com
JOHN SMITH      john@gmail.com
JOHN SMITH      john.smith@hotmail.com
MARY SMITH      mary@hotmail.com
PHILL TAYLOR    phill@hotmail.com
PHILL TAYLOR    phill@gmail.com
PHILL TAYLOR    taylor.phill@hotmail.com
PHILL TAYLOR    taylor.phill@gmail.com
但我需要将所有电子邮件放在同一行中,以满足预定义的布局:

NAME            EMAIL1              EMAIL2          EMAIL3                      EMAIL4
-------------   -----------------   --------------- -----------------------     -----------------
JOHN SMITH      john@hotmail.com    john@gmail.com  john.smith@hotmail.com
MARY SMITH      mary@hotmail.com
PHILL TAYLOR    phill@hotmail.com   phill@gmail.com taylor.phill@hotmail.com    taylor.phill@hotmail.com
是否可以使用单一选择

任何想法都将不胜感激

短暂性脑缺血发作


里卡多·诺盖拉(Ricardo Nogueira)

它不漂亮,存在使用问题等。但如果你必须的话。。你必须。。因此,使用您的模式,这是:-

create function dbo.emails(@NameId int, @Ordinal int)
returns varchar(1024)
as begin
    declare @returnValue varchar(1024)
    select @returnValue=email
    from (
        select 
            ROW_NUMBER() over (order by e.Email) as ordinal,
            e.Email
        from Email e
        where e.NameId=@NameId
    ) p1 
    where p1.ordinal=@Ordinal
    return @returnValue
end
go
select e.Name,
    dbo.emails(n.NameId,1) as email1,
    dbo.emails(n.NameId,2) as email2,
    dbo.emails(n.NameId,3) as email3,
    dbo.emails(n.NameId,4) as email4
from Name n
go
产生:-

Name          email1                  email2             email3                  email4
JOHN SMITH    john.smith@hotmail.com  john@gmail.com     john@hotmail.com        NULL
MARY SMITH    mary@hotmail.com        NULL               NULL                    NULL
PHILL TAYLOR  phill@gmail.com         phill@hotmail.com  taylor.phill@gmail.com  taylor.phill@hotmail.com

它可以在1个选择中完成。如果您只需要前4个电子邮件地址,并将其用作特定列。使用电子邮件表上的RowNumber函数为每个用户的邮件地址编号。本例假设电子邮件地址应按字母顺序排序:

with m as (
  select 
    ROW_NUMBER() over (partition by nameId order by email) as Nr, 
    email.NameId, email.Email 
  from email
)
select 
  name.NameId, 
  name.Name, 
  m1.Email as Mail1,
  m2.Email as Mail2,
  m3.Email as Mail3,
  m4.Email as Mail4
from name
left join m m1 on (m1.Nr=1 and m1.NameId=name.NameId)
left join m m2 on (m2.Nr=2 and m2.NameId=name.NameId)
left join m m3 on (m3.Nr=3 and m3.NameId=name.NameId)
left join m m4 on (m4.Nr=4 and m4.NameId=name.NameId)

逗号分隔的值是否可以执行此任务?这要简单得多。你是说,如果名字相同,那么电子邮件地址指的是同一个人吗?这与实际情况不符,除非您将其限制在某些(问题中未说明)标准内。您所说的预定义布局是什么意思?我的意思是你的预定义布局是什么?逗号删除的电子邮件列表可以吗?是的,最终的目的是将select导出到CVS,但是布局定义了每行一个人,所有他/她的电子邮件并排在一起。问题在哪里提到高性能?有时候你必须提供一个实用的解决方案。对我来说,糟糕的数据库设计是不实用的。用户user2970362给出了一个实用的解决方案,它的性能也很好。您实现它的方式正是“一行一行”性能问题的范例,即糟糕的数据库设计。