三向全外连接/表合并

时间:2011-06-10 21:24:02

标签: sql-server sql-server-2000 full-outer-join

我想在三个表上执行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  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列合并表格。

  

这提出了我如何做的问题   希望在另一方解决冲突   列值不同。算法   可用于解决用户名和FullName之间冲突的原因是:

 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......

2 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:1)

在您给出的示例中,您根本不需要加入。我希望,这是一个真实的例子,而不是一个人为的例子。你想做的事情在这里非常简单,根本不需要连接,你不需要row_number。你可以这样做:

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