在公共列上联接三个表

时间:2019-09-22 21:44:47

标签: sql sql-server

我有三个表,分别为Table1,Table2和Table3。表1具有列(mobNum bigint,visitedUS DateTime)。 Table2具有Columns(mobNum bigint,visitedUK DateTime)。 Table3具有Columns(mobNum bigint,visitedChina DateTime)。样本数据如下

表1

___________________________       
    mobnum | visitedUS
___________________________ 
9000000001 |  20/10/18  
___________________________ 
9000000001 | 11/07/19  
___________________________ 
9000000002 | 01/02/17
___________________________

表2

    mobnum | visitedUK
___________________________ 
9000000001 | 03/05/19  
___________________________ 
9000000002 |10/10/18  
___________________________

表3

    mobnum | visitedChina
___________________________ 
9000000001 | 15/03/18 
___________________________ 

现在我希望SQL查询显示如下结果

              Result Table
   -------------------------------------------------------
   mobnum      | visitedUS    | visitedUK  | visitedChina  
   -------------------------------------------------------
     9000000001|20/10/18      |  03/05/19  |  15/03/18    
   -------------------------------------------------------
     9000000001|11/07/19      |  Null      |   Null       
   -------------------------------------------------------
     9000000002|01/02/17      | 10/10/18   |   Null       
   -------------------------------------------------------

5 个答案:

答案 0 :(得分:2)

我没有测试或仔细检查拼写/语法:

select 
    isnull(t1.mobnum,isnull(t2.mobnum,t3.mobnum)) mobnum,
    t1.visitedUS, 
    t2.visitedUK, 
    t3.visitedChina
from Table1 t1
full outer join Table2 t2 on t1.mobnum = t2.mobnum
full outer join Table3 t3 on t3.mobnum = isnull(t1.mobnum,t2.mobnum)

答案 1 :(得分:1)

CREATE TABLE [dbo].[Table1](
    [mobnum] [bigint] NULL,
    [visitedUS] [date] NULL
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[Table2](
    [mobnum] [bigint] NULL,
    [visitedUK] [date] NULL
) ON [PRIMARY]

CREATE TABLE [dbo].[Table3](
    [mobnum] [bigint] NULL,
    [visitedChina] [date] NULL
) ON [PRIMARY]
GO
INSERT [dbo].[Table1] ([mobnum], [visitedUS]) VALUES (9000000001, CAST(N'2018-10-20' AS Date))
GO
INSERT [dbo].[Table1] ([mobnum], [visitedUS]) VALUES (9000000002, CAST(N'2018-10-30' AS Date))
GO
INSERT [dbo].[Table2] ([mobnum], [visitedUK]) VALUES (9000000001, CAST(N'2018-11-10' AS Date))
GO
INSERT [dbo].[Table2] ([mobnum], [visitedUK]) VALUES (9000000003, CAST(N'2018-11-25' AS Date))
GO
INSERT [dbo].[Table3] ([mobnum], [visitedChina]) VALUES (9000000001, CAST(N'2018-12-01' AS Date))
GO
INSERT [dbo].[Table3] ([mobnum], [visitedChina]) VALUES (9000000004, CAST(N'2018-12-10' AS Date))
GO

现在检查以下查询

SELECT ISNULL(t1.mobnum, ISNULL(t2.mobnum, t3.mobnum)) mobnum,
       t1.visitedUS,
       t2.visitedUK,
       t3.visitedChina
FROM Table1 t1
    FULL OUTER JOIN Table2 t2
        ON t1.mobnum = t2.mobnum
    FULL OUTER JOIN Table3 t3
        ON t3.mobnum = ISNULL(t1.mobnum, t2.mobnum);

答案 2 :(得分:1)

仅用2美分,一个更干净的解决方案是使用colesce而不是多个ISNULL:

SELECT COALESCE(t1.mobnum, t2.mobnum, t3.mobnum) mobnum,
       t1.visitedUS,
       t2.visitedUK,
       t3.visitedChina
FROM Table1 t1
    FULL OUTER JOIN Table2 t2 ON t1.mobnum = t2.mobnum
    FULL OUTER JOIN Table3 t3 ON t3.mobnum = ISNULL(t1.mobnum, t2.mobnum);

答案 3 :(得分:0)

当每个表中都有多行时,

FULL OUTER JOIN将创建有趣的结果集。解决此问题的更好方法是使用union allrow_number()group by

select mobnum,
       max(visitedUS) as visitedUS,
       max(visitedUK) as visitedUK,
       max(visitedChina) as visitedChina
from ((select mobnum, visitedUS, null as visitedUS, null as visitedChina,
              row_number() over (partition by mobnum order by visitedUS) as seqnum
       from table1
      ) union all
      (select mobnum, null as visitedUS, visitedUK, null as visitedChina,
              row_number() over (partition by mobnum order by visitedUK) as seqnum
       from table2
      ) union all
      (select mobnum, null as visitedUS, null as visitedUK, visitedChina,
              row_number() over (partition by mobnum order by visitedChina) as seqnum
       from table1
      )
     ) v
group by mobnum, seqnum;

答案 4 :(得分:0)

尝试一下:

with table1rn(mobnum, visitedUS, rn) as
(
select *, row_number() over(partition by mobnum order by visitedUS) rn
from table1
),
table2rn(mobnum, visitedUK, rn) as
(
select *, row_number() over(partition by mobnum order by visitedUK) rn
from table2
),
table3rn(mobnum, visitedChina, rn) as
(
select *, row_number() over(partition by mobnum order by visitedChina) rn
from table3
)
select t1.mobnum, t1.visitedUS, t2.visitedUK, t3.visitedChina
from table1rn t1
left join table2rn t2 on t2.mobnum = t1.mobnum and t2.rn = t1.rn
left join table3rn t3 on t3.mobnum = t1.mobnum and t3.rn = t1.rn