Sql server 三向完全外部联接/表合并

Sql server 三向完全外部联接/表合并,sql-server,sql-server-2000,full-outer-join,Sql Server,Sql Server 2000,Full Outer Join,我想在三个表上执行完整的外部联接,合并公共行 SELECT * FROM Users id Username Fullname == ======== ===================== 7 iboyd Ian Boyd 8 nicholle Nicholle Kuzniak 10 jamie Jamie Bellaire 3 row(s) affected SELECT * FROM GrobUsers id Username Full

我想在三个表上执行完整的外部联接,合并公共行

SELECT * FROM Users

id  Username  Fullname
==  ========  =====================
 7  iboyd     Ian Boyd
 8  nicholle  Nicholle Kuzniak
10  jamie     Jamie Bellaire

3 row(s) affected


SELECT * FROM GrobUsers

id  Username  Fullname
==  ========  =====================
 7  iboyd     Ian Alexander Boyd 
 8  nicholle  Nicholle Bachand
 9  chris     Chris Windibank

3 row(s) affected


SELECT * FROM FrobUsers

id  Username  Fullname
==  ========  =====================
 7  ian       Ian
 9  chris     Chris W.
10  jamie     James Bellaire

3 row(s) affected
我想根据id列合并表

这就引出了一个问题:我该如何做 希望冲突在对方 列值不同。算法 可用于解决用户名和全名之间冲突的是:

 if (id's are equal) then 
    pick one; i don't care
我尝试了以下几点:

SELECT
   COALESCE(Users.id, GrobUsers.id, FrobUsers.id) AS id,
   COALESCE(Users.Username, GrobUsers.Username, FrobUsers.Username) AS Username,
   COALESCE(Users.FullName, GrobUsers.FullName, FrobUsers.FullName) AS Fullname
FROM Users
   FULL OUTER JOIN GrobUsers ON GrobUsers.id = Users.id

   FULL OUTER JOIN FrobUsers ON FrobUsers.id = .....something......

一个典型的技巧是使用一个没有意义的聚合函数

select id, min(username), min(fullname) from (
  SELECT * FROM Users 
  union
  SELECT * FROM FrobUsers
  union
  SELECT * FROM GrobUsers  
) as foo
group by foo.id
嗯。。。但它可以从一个表中选择用户名,从另一个表中选择全名。如果你还是不在乎,用它,否则。。。也许吧

select id, username, fullname from (
  select id, username, fullname, takeme = row_number() over (partition by id)
  from (
    SELECT * FROM Users 
    union
    SELECT * FROM FrobUsers
    union
    SELECT * FROM GrobUsers  
  ) as foo
) as bar
where bar.takeme = 1

在您给出的示例中,您根本不需要联接。我希望这是一个真实的例子,而不是人为的。这里要做的很简单,根本不需要连接,也不需要行号。您可以这样做:

select id,Username,Fullname from Users
UNION ALL
select id,Username,Fullname from GrobUsers 
where id not in (select id from Users)
UNION ALL
select id,Username,Fullname from FrobUsers  
where id not in (select id from Users) and id not in (select id from GrobUsers)
它会给你这个:

id          Username   Fullname        
----------- ---------- -----------------
7           iboyd      Ian Boyd         
8           nicholle   Nicholle Kuzniak 
9           chris      Chris Windibank  
10          jamie      Jamie Bellaire   

(4 row(s) affected)
以下是我使用的测试用例:

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Users]') AND type in (N'U'))
DROP TABLE [dbo].[Users]
GO

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[GrobUsers]') AND type in (N'U'))
DROP TABLE [dbo].[GrobUsers]
GO

IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[FrobUsers]') AND type in (N'U'))
DROP TABLE [dbo].[FrobUsers]
GO

CREATE TABLE [dbo].[Users](
    [Id] [int] NOT NULL,
    [Username] [nchar](50) NULL,
    [Fullname] [nchar](50) NULL,
 CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

CREATE TABLE [dbo].[GrobUsers](
    [Id] [int] NOT NULL,
    [Username] [nchar](50) NULL,
    [Fullname] [nchar](50) NULL,
 CONSTRAINT [PK_GrobUsers] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

CREATE TABLE [dbo].[FrobUsers](
    [Id] [int] NOT NULL,
    [Username] [nchar](50) NULL,
    [Fullname] [nchar](50) NULL,
 CONSTRAINT [PK_FrobUsers] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

INSERT INTO Users Values (7,'iboyd','Ian Boyd' )
INSERT INTO Users Values (8,'nicholle','Nicholle Kuzniak' )
INSERT INTO Users Values (10,'jamie','Jamie Bellaire' )


INSERT INTO [GrobUsers] Values (7,'iboyd','Ian Alexander Boyd ' )
INSERT INTO [GrobUsers] Values (8,'nicholle','Nicholle Bachand' )
INSERT INTO [GrobUsers] Values (9,'chris','Chris Windibank' )

INSERT INTO [FrobUsers] Values (7,'iboyd','Ian' )
INSERT INTO [FrobUsers] Values (9,'nicholle','Chris W.' )
INSERT INTO [FrobUsers] Values (10,'jamie','James Bellaire' )
GO

我在这台计算机上没有开发工具,所以没有尝试过这个方法,但是您可以使用交叉应用,然后使用由其中一个ID字段划分的行数重新查询,并返回行数为1的行吗?如果您将表合并在一起,然后使用由ID字段划分的行数查询结果,然后,您可以在行号为1的位置获得匹配的用户名和全名。@Duncan这正是我在此期间键入的内容:我想您在select子句中指的是id,而不是if。我试着编辑它,但编辑需要超过6个字符…当使用where id not in时,你可以通过使用union all而不是union来保存服务器的一些工作。我将把它交给zespri,因为他的解决方案在2000年工作,这就是我正在使用的,并且从同一行获取用户名和全名。但是@GSerg,你的想法也很好@伊恩博伊德,你的编辑让人费解。你想完成什么?@IanBoyd,好的,有道理。我将在几分钟后删除我的此评论和以前的评论。