SQL联接和MS Access - 如何将多个表组合成一个?

时间:2014-07-03 18:58:55

标签: sql ms-access join ms-access-2010

我在Access 2010中有四个表,每个表都有相同的主键。我想将所有四个表中的所有数据连接到一个表中,每个表的列与每个表上的主键相关联。所以,例如:

Table1

ID   Value1

1    10       
2    7
3    4
4    12

Table 2

ID   Value2

1    33
2    8
6    19
7    4

Table 3

ID   Value3

1    99
2    99
5    99
7    99

我想创建:

Table 4

ID  Value1  Value2  Value3

1   10      33      99
2   7       8       99
3   4
4   12
5           99
6           19      
7           4       99

我正在使用MS Access,我知道我必须基本上使用3个连接(左,右,内)来获得完整连接,但我不确定如何构建查询。

有人可以给我一些示例SQL代码,指出我如何产生这个结果的正确方向?

这是我到目前为止所拥有的。这结合了所有表格,但看起来我仍然缺少一些数据。我做错了什么:

SELECT Coventry.cptcode, Coventry.[Fee Schedule], CT6002.[Fee Schedule], Medicare.[Fee Schedule], OFSP.[Fee Schedule]
FROM ((Coventry LEFT JOIN CT6002 ON Coventry.cptcode = CT6002.cptcode) LEFT JOIN Medicare ON CT6002.cptcode = Medicare.cptcode) LEFT JOIN OFSP ON Medicare.cptcode = OFSP.cptcode
UNION
SELECT Coventry.cptcode, Coventry.[Fee Schedule], CT6002.[Fee Schedule], Medicare.[Fee Schedule], OFSP.[Fee Schedule]
FROM ((Coventry RIGHT JOIN CT6002 ON Coventry.cptcode = CT6002.cptcode) RIGHT JOIN Medicare ON CT6002.cptcode = Medicare.cptcode) RIGHT JOIN OFSP ON Medicare.cptcode = OFSP.cptcode
UNION
SELECT Coventry.cptcode, Coventry.[Fee Schedule], CT6002.[Fee Schedule], Medicare.[Fee Schedule], OFSP.[Fee Schedule]
FROM ((Coventry INNER JOIN CT6002 ON Coventry.cptcode = CT6002.cptcode) INNER JOIN Medicare ON CT6002.cptcode = Medicare.cptcode) INNER JOIN OFSP ON Medicare.cptcode = OFSP.cptcode;

3 个答案:

答案 0 :(得分:2)

创建所有表中所有id的并集,这样就可以获得table4中的id列。然后将此并集封装在子选择(ids)中,并在此子选择(父连接)和table1,table2,table3(子连接)之间创建左连接。然后选择你需要的东西......

SELECT 
ids.id, 
t1.Value1, 
t2.Value2, 
t3.Value3
FROM ((
(select id from table1 
union 
select id from table2
union 
select id from table3)  AS ids 
LEFT JOIN Table1 AS t1 ON ids.id = t1.ID) 
LEFT JOIN Table2 AS t2 ON ids.id = t2.ID) 
LEFT JOIN Table3 AS t3 ON ids.id = t3.ID;

答案 1 :(得分:1)

这个怎么样?

SELECT id
, max(v1) as value1
, max(v2) as value2
, max(v3) as value3
FROM 
(
    select id
    , value1 as v1
    , iif(true,null,value1) as v2
    , iif(true,null,value1) as v3 
    from Table1

    union 

    select id, null , value2 , null  from Table2

    union 

    select id, null , null , value3 as v3 from Table3
)
group by id
order by id

工作原理:

  • 我没有进行连接,而是将所有结果放入一个" table" (我的子查询),但是在自己的列中使用value1,value2和value3,并且对于不具有这些列的表,将其设置为null。

  • 第一个查询中的iif语句是说我希望v2和v3与v1是相同的数据类型。这是一个狡猾的黑客,但似乎工作(遗憾的是访问从查询中的第一个语句开始计算,而clng(null)投射不起作用)。它们起作用是因为iif的结果必须与最后两个参数的类型相同,并且只有最后一个参数有一个类型,因此可以从中推断出来;第一个参数为true表示返回的值只是第二个参数。

  • 外部查询然后将这些结果压缩到每个id一行;因为具有值的字段大于null并且我们最多只有一个字段具有每个id的值,所以我们得到该列的值。

我不确定性能与MS文章的执行方式相比如何,但如果您使用访问权限,我怀疑您还有其他事情需要担心;)。

SQL小提琴:http://sqlfiddle.com/#!6/6f93b/2 (对于SQL Server,因为Access不可用,但我已尝试使其尽可能相似)

答案 2 :(得分:0)

如果[Value1],[Value2]和[Value3]属于不同类型,这是JohnLBevan的答案的变体。例如,使用

表1

ID  Value1
--  ------
 1      10
 2       7
 3       4
 4      12

表2

ID  Value2      
--  ------------
 1  thirty-three
 2  eight       
 6  nineteen    
 7  four        

表3

ID  Value3    
--  ----------
 1  1999-01-01
 2  1999-01-01
 5  1999-01-01
 7  1999-01-01

查询

SELECT ID, MAX(v1) AS Value1, MAX(v2) AS Value2, MAX(v3) as Value3
FROM (
        SELECT 0 AS ID, 0 AS v1, '' AS v2, #2001-01-01# AS v3
        FROM (SELECT COUNT(*) FROM Table1)
    UNION ALL
        SELECT ID, Value1 AS v1, NULL AS v2, NULL AS v3
        FROM Table1
    UNION ALL
        SELECT ID, NULL AS v1, Value2 AS v2, NULL AS v3
        FROM Table2
    UNION ALL
        SELECT ID, NULL AS v1, NULL AS v2, Value3 AS v3
        FROM Table3
)
WHERE ID > 0
GROUP BY ID

返回

ID  Value1  Value2        Value3    
--  ------  ------------  ----------
 1      10  thirty-three  1999-01-01
 2       7  eight         1999-01-01
 3       4                          
 4      12                          
 5                        1999-01-01
 6          nineteen                
 7          four          1999-01-01

<强>解释

UNION子查询的第一部分创建一个具有虚拟值的行,以确保UNION的结果具有正确的列类型

SELECT 0 AS ID, 0 AS v1, '' AS v2, #2001-01-01# AS v3
FROM (SELECT COUNT(*) FROM Table1)

返回

ID  v1  v2  v3        
--  --  --  ----------
 0   0      2001-01-01

UNION子查询的其余部分追加每个表的实际行

    SELECT 0 AS ID, 0 AS v1, '' AS v2, #2001-01-01# AS v3
    FROM (SELECT COUNT(*) FROM Table1)
UNION ALL
    SELECT ID, Value1 AS v1, NULL AS v2, NULL AS v3
    FROM Table1
UNION ALL
    SELECT ID, NULL AS v1, Value2 AS v2, NULL AS v3
    FROM Table2
UNION ALL
    SELECT ID, NULL AS v1, NULL AS v2, Value3 AS v3
    FROM Table3

给我们

ID  v1  v2            v3        
--  --  ------------  ----------
 0   0                2001-01-01
 1  10                          
 2   7                          
 3   4                          
 4  12                          
 1      thirty-three            
 2      eight                   
 6      nineteen                
 7      four                    
 1                    1999-01-01
 2                    1999-01-01
 5                    1999-01-01
 7                    1999-01-01

外部聚合查询排除带有虚拟值的第一行(WHERE ID> 0),每个ID给出一行(GROUP BY ID),并使用MAX()函数返回一个值(如果有的话) (如果没有,则为空。)

ID  Value1  Value2        Value3    
--  ------  ------------  ----------
 1      10  thirty-three  1999-01-01
 2       7  eight         1999-01-01
 3       4                          
 4      12                          
 5                        1999-01-01
 6          nineteen                
 7          four          1999-01-01