sql 两条数据 空值合并_Excel VBA+ADO+SQL入门教程12:多表数据合并

博客围绕SQL数据处理展开,涉及两条数据空值合并、两表数据合并、去重复、字段汇总、保留唯一记录以及两字段相除等内容,还提及了Excel零基础教程、工作日计算及连续区间查询方法等相关信息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

点上方关注我们,每日1练,每天进步一点点1a114266f64660d7ea2020d4f422c6e7.gif

 1.

SQL的UNION运算符可以合并两个或多个的SELECT语句的查询结果,因此,我们通常使用它来合并多表数据。例如,在一个工作簿中存在两个表,一个表名为 '一班',另一个表名为'二班',现在我们需要将两个表的数据合并成一张表。a7b128f0175ae0968ea609ee5da88d46.png          SQL语句如下:
SELECT *  FROM [一班$] UNION SELECT *  FROM [二班$]
结果如下:3299924a1ec4f598f4435fb9b59c7909.png          需要说明的是,UNION会对合并的结果去重复,只保留唯一值;前面讲去重复的时候提过,SQL去重复的过程,是先对记录排序,后再去重复,因此UNION的运算结果通常是默认升序排列的不重复记录。例如,汇总一班和二班两个班级的学生名单:
SELECT 姓名  FROM [一班$] UNION SELECT 姓名  FROM [二班$]
结果如下:07832322d4901874a40697081b7ec5eb.png          由于使用了UNION运算符,一、二班都存在的‘看见星光‘,只保留了一个。如果不需要去重复的操作,可以使用关键字ALL,也就是UNION ALL。同样汇总一班和二班两个班级的学生名单:
SELECT 姓名  FROM [一班$] UNION ALL SELECT 姓名  FROM [二班$]
结果如下:        29eb9f502b46aaea89f3c70e97b7d37b.png          由于使用了ALL关键字,一、二班都存在的‘看见星光‘,都被保留了下来;而且姓名的排放顺序是和出现的顺序一致的,并没有进行排序处理。

 2.

不管是UNION还是UNION ALL,都要求SELECT语句拥有相同的列数,而且字段的排放顺序必须相同。当列数不相同时,例如以下语句:
SELECT 姓名,语文  FROM [一班$] UNION ALL SELECT 姓名  FROM [二班$]
会得到错误提示:f5097c98a20acf5d76205562a0249120.png          而当列的个数相同,但顺序不相同时,例如以下语句:
SELECT 姓名,语文  FROM [一班$] UNION ALL SELECT 语文,姓名  FROM [二班$]
会得出错误的结果。62e87a873b9c8bf6b8f25eb2ed65e320.png          之所以语句能够运算,但结果不尽人意(姓名列出现了语文的成绩),是因为UNION运算符总是按第一个SELECT语句中字段的排放顺序处理数据的。第一个SELECT指定了'姓名'字段第1列、'语文'字段第2列,则默认以后的SELECT语句第1列均为'姓名'字段,第2列均为'语文'。此外,UNION运算符总是将第一个SELECT语句提供的字段名称作为最终查询结果的字段名称。例如,以下语句只是在第一个SELECT子句中使用了别名,但查询结果中的字段名依然是按照指定别名呈现的。
SELECT 姓名,语文 AS 语文成绩  FROM [一班$] UNION ALL SELECT 姓名,语文  FROM [二班$]
be69442f8634fb5f2b273e2283e5efcc.png          

 3.

在实际汇总多表数据的过程中,难免会碰到表格列数不一致的情况。例如,以下两个表,名字为‘一班‘的表字段由姓名、语文、数学和英语构成,而另外一个名为’二班‘的表字段只有姓名、语文和英语,并没有数学字段。如果此时我们进行两表数据汇总,应该怎么处理呢?a04780769413cc1aa62234555fcf355b.png          对于缺少的字段可以使用某个值代替。通常是使用NULL代替,语句如下:
SELECT 姓名,语文,数学,英语  FROM [一班$] UNION ALL SELECT 姓名,语文,NULL,英语 FROM [二班$]

结果如下:5cda8de28e9808e7500451b5a96e9fd4.png          当然,也可以使用其它值代替,例如‘未考’,语句如下:
SELECT 姓名,语文,数学,英语  FROM [一班$] UNION ALL SELECT 姓名,语文,'未考',英语  FROM [二班$]
结果如下:9279d9ffe5431792df6e6dfa787d18e0.png          

 4.

当需要汇总的表格列数统一,但个数过多时,手工输入SQL语句未免不够灵活方便,此时最好是使用VBA的方式。以本文的第1图为例:
Sub SQL_UNION()    Dim cnn As Object, rst As Object    Dim strPath As String, str_cnn As String    Dim strSQL As String, strTemp As String    Dim sht As Worksheet, strShtName As String    Dim i As Long    Set cnn = CreateObject("adodb.connection")    strPath = ThisWorkbook.FullName    If Application.Version < 12 Then        str_cnn = "Provider=Microsoft.jet.OLEDB.4.0;Extended Properties=Excel 8.0;Data Source=" & strPath    Else        str_cnn = "Provider=Microsoft.ACE.OLEDB.12.0;Extended Properties=Excel 12.0;Data Source=" & strPath    End If    cnn.Open str_cnn    strTemp = "SELECT 姓名,语文,数学,英语,"    For Each sht In Worksheets        strShtName = sht.Name        If strShtName <> ActiveSheet.Name Then            strSQL = strSQL & strTemp & "'" & strShtName & "' AS 班级 FROM [" & strShtName & "$] UNION ALL "        End If    Next    strSQL = Left(strSQL, Len(strSQL) - 11)    Set rst = cnn.Execute(strSQL)    Cells.ClearContents    For i = 0 To rst.Fields.Count - 1        Cells(1, i + 1) = rst.Fields(i).Name    Next    Range("a2").CopyFromRecordset rst    cnn.Close    Set cnn = NothingEnd Sub
运算结果如下:81381277033e55a8ff1de1f6b53aba27.png          代码中,变量strTemp指定了需要汇总的字段名称和顺序;之后通过对工作表对象的遍历,合并多个select语句,并将工作表名称作为一个字段补充到SELECT子句中,最后使用ADO执行SQL语言获得查询结果。而当需要汇总的表格标题名称统一,但列数并不统一,表格个数又过多时,可以借助字典先对列标题和排列顺序做一个过滤储存,然后再编写和执行SQL语句……刹车刹车,没油了,这个问题我们以后再谈,握爪致安,下期再见。小贴士:您可能见过这样的多表合并SQL语句,使用通配符*,代替字段名的描述:
SELECT * FROM  [一班$] UNION ALL SELECT * FROM [二班$]
但作为模板应用,我们通常并不推荐使用这种方式,至于缘故,我们在【Excel VBA+ADO+SQL入门教程009:聚合函数】的小贴士里做了说明,此处就不再重复了。下载示例文件:
https://pan.baidu.com/s/1nQcyPcXsIHeqkVKn3wz5yg
提取码: ww8r 系统学习Excel,推荐加入我的Excel社群

2fd9c13cfe00fd2a0e365d0b188c7735.png

更多教程&练习

  • 001:零基础学Excel(一)什么是Excel?

  • 002:30个工作日后(含特定节假日)是哪天?

  • 003:连续区间查询的常用方法有哪些?


©看见星光c10ac8f256f491929eae609d1c29a349.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值