MySQL 合并查询union 查询出的行合并到一个表中
在合并查询中,尤其是二分类的情况,在查询结果是相同列名的时候可以考虑合并查询。先查询出行的结果,再使用union或者union all合并查询结果。
另外如果 union 和 order by 一起使用的话要注意使用方法。
一、适用场景和方法
(1)适用场景
考虑查询过程中是否存在以下情况:
查询行时用的表不同;
查询某些行时需要where条件,某些行不需要where条件;
分类查询;
查询的结果具有相同的列名。
存在上述情况时,大多数需要合并查询。先分行查询,再将查询出的行合并到一个表中。
(2)方法
MySQL合并查询,将查询到的行(具有相同列)合并到一个表中使用union或者union all函数
具体包括:
| 函数 | 使用说明 |
|---|---|
| union | 出现相同行时,不保留重复行,进行去重处理 |
| union all | 出现相同行时,保留重复行,不进行去重 |
根据查询需要使用不同合并函数。
二、案例分析
下面用2个具体的案例(由简到难)来说明行合并的过程:
(1)简单案例
描述
现在运营想要将用户划分为25岁以下和25岁及以上两个年龄段,分别查看这两个年龄段用户数量
本题注意:age为null 也记为 25岁以下
示例:user_profile
| id | device_id | gender | age | university | gpa | active_days_within_30 | question_cnt | answer_cnt |
|---|---|---|---|---|---|---|---|---|
| 1 | 2138 | male | 21 | 北京大学 | 3.4 | 7 | 2 | 12 |
| 2 | 3214 | male | 复旦大学 | 4 | 15 | 5 | 25 | |
| 3 | 6543 | female | 20 | 北京大学 | 3.2 | 12 | 3 | 30 |
| 4 | 2315 | female | 23 | 浙江大学 | 3.6 | 5 | 1 | 2 |
| 5 | 5432 | male | 25 | 山东大学 | 3.8 | 20 | 15 | 70 |
| 6 | 2131 | male | 28 | 山东大学 | 3.3 | 15 | 7 | 13 |
| 7 | 4321 | male | 26 | 复旦大学 | 3.6 | 9 | 6 | 52 |
根据示例,你的查询应返回以下结果:
| age_cut | number |
|---|---|
| 25岁以下 | 4 |
| 25岁及以上 | 3 |
【分类】:合并查询、多表连接
分析思路
难点:
1.单个字符或者值可以作为一列:例如'activity2' as activity
2.用了一半时间就完成高难度试卷。两个时间相减得到分钟:timestampdiff(minute, date_expr1, date_expr2) 两个时间的差
(1)统计25岁以下学生的人数
[条件]:where score >= 85 and year(start_time) = 2021
[使用]:distinct。一定要去重
(2)统计25岁以上学生的人数
[条件]:where difficulty = 'hard' and score > 80 and year(start_time) = 2021 and timestampdiff(minute, start_time, submit_time) < duration / 2
[使用]:多表连接使用 join using( )
(3)合并两个表
[使用]:union all 和union 都可以,因为列activity不会有重复。
最终结果
(
select 查询结果 [年龄段; 人数]
from 从哪张表中查询数据[用户表]
where 查询条件 [年龄小于25或者为空]
)
union
(
select 查询结果 [年龄段; 人数]
from 从哪张表中查询数据[用户表]
where 查询条件 [年龄大于25]
)
该题的多种解法详见:SQL26 计算25岁以上和以下的用户数量
求解代码
union
(
#统计25岁以下学生的人数
select
'25岁以下' as age_cut,
count(device_id) as number
from user_profile
where age < 25 or age is null
)
union
(
#统计25岁以上学生的人数
select
'25岁及以上' as age_cut,
COUNT(device_id) as number
from user_profile
where age >= 25
)
(2)较难案例
案例来自:SQL132 每个题目和每份试卷被作答的人数和次数
描述
现有试卷作答记录表exam_record(uid用户ID, exam_id试卷ID, start_time开始作答时间, submit_time交卷时间, score得分):
| id | uid | exam_id | start_time | submit_time | score |
|---|---|---|---|---|---|
| 1 | 1001 | 9001 | 2021-09-01 09:01:01 | 2021-09-01 09:41:01 | 81 |
| 2 | 1002 | 9002 | 2021-09-01 12:01:01 | 2021-09-01 12:31:01 | 70 |
| 3 | 1002 | 9001 | 2021-09-01 19:01:01 | 2021-09-01 19:40:01 | 80 |
| 4 | 1002 | 9002 | 2021-09-01 12:01:01 | 2021-09-01 12:31:01 | 70 |
| 5 | 1004 | 9001 | 2021-09-01 19:01:01 | 2021-09-01 19:40:01 | 85 |
| 6 | 1002 | 9002 | 2021-09-01 12:01:01 | (NULL) | (NULL) |
题目练习表practice_record(uid用户ID, question_id题目ID, submit_time提交时间, score得分):
| id | uid | question_id | submit_time | score |
|---|---|---|---|---|
| 1 | 1001 | 8001 | 2021-08-02 11:41:01 | 60 |
| 2 | 1002 | 8001 | 2021-09-02 19:30:01 | 50 |
| 3 | 1002 | 8001 | 2021-09-02 19:20:01 | 70 |
| 4 | 1002 | 8002 | 2021-09-02 19:38:01 | 70 |
| 5 | 1003 | 8001 | 2021-08-02 19:38:01 | 70 |
| 6 | 1003 | 8001 | 2021-08-02 19:48:01 | 90 |
| 7 | 1003 | 8002 | 2021-08-01 19:38:01 | 80 |
请统计每个题目和每份试卷被作答的人数和次数,分别按照"试卷"和"题目"的uv & pv降序显示,示例数据结果输出如下:
| tid | uv | pv |
|---|---|---|
| 9001 | 3 | 3 |
| 9002 | 1 | 3 |
| 8001 | 3 | 5 |
| 8002 | 2 | 2 |
解释:“试卷”有3人共练习3次试卷9001,1人作答3次9002;“刷题”有3人刷5次8001,有2人刷2次8002
【分类】:合并查询
分析思路
难点:
- union 和 order by 一起使用需要注意的问题
(1)统计每份试卷被作答的人数和次数
[条件]:where score >= 85 and year(start_time) = 2021
[使用]:distinct。一定要去重
(2)统计每个题目被作答的人数和次数
[条件]:where difficulty = 'hard' and score > 80 and year(start_time) = 2021 and timestampdiff(minute, start_time, submit_time) < duration / 2
[使用]:多表连接使用 join using( )
(3)合并两个表,分别按照"试卷"和"题目"的uv & pv降序显示
[使用]:union all 和union 都可以,因为列activity不会有重复。
最终结果
select * from
(
select 查询结果 [试卷ID; 作答次数]
from 从哪张表中查询数据[试卷作答记录表]
group by 分组条件 [试卷ID]
order by 对查询结果排序 [按照"试卷"的uv & pv降序]
)
union
select * from
(
select 查询结果 [题目ID; 作答次数]
from 从哪张表中查询数据[题目练习表]
group by 分组条件 [题目ID]
order by 对查询结果排序 [按照"题目"的uv & pv降序]
)
求解代码
方法一:
#正确代码
select * from
(
select
exam_id as tid,
count(distinct uid) as uv,
count(uid) as pv
from exam_record a
group by exam_id
order by uv desc, pv desc
) a
union
select * from
(
select
question_id as tid,
count(distinct uid) as uv,
count(uid) as pv
from practice_record b
group by question_id
order by uv desc, pv desc
) attr
是不是可以union两个子句之后再使用order by ? 但是这个排序要对2个表分别进行降序,就需要写成下面这样:
方法二:
使用函数
left(str,length) 函数: str左边开始的长度为 length 的子字符串,在本例中为‘9’和‘8’
解释:试卷编号以‘9’开头、题目编号以‘8’开头,对编号进行降序就是对"试卷"和"题目"分别进行排序
(
#每份试卷被作答的人数和次数
select
exam_id as tid,
count(distinct uid) as uv,
count(*) as pv
from exam_record
group by exam_id
)
union
(
#每个题目被作答的人数和次数
select
question_id as tid,
count(distinct uid) as uv,
count(*) as pv
from practice_record
group by question_id
)
#分别按照"试卷"和"题目"的uv & pv降序显示
order by left(tid,1) desc,uv desc,pv desc
推荐使用方法一,更具有普适性。
扩展:
前往查看MySQL union 和 order by 一起使用需要注意的问题
MySQL 合并查询union 查询出的行合并到一个表中的更多相关文章
- exp导出一个表中符合查询条件的数据
原文地址:exp导出一个表中符合查询条件的数据 作者:charsi 导出一个表中的部分数据,使用QUERY参数,如下导出select * from test where object_id>50 ...
- ORACLE 查询一个数据表后通过遍历再插入另一个表中的两种写法
ORACLE 查询一个数据表后通过遍历再插入另一个表中的两种写法 语法 第一种: 通过使用Oracle语句块 --指定文档所有部门都能查看 declare cursor TABLE_DEPT and ...
- Linq 中查询一个表中指定的字段
//Linq中查询一个表中指定的几个字段: ); // FindAllItems()为查询对应表的所有数据的方法: // Where 里面为查询条件 // Select 为查询的筛选条件 new{} ...
- 对一个表中所有列数据模糊查询adoquery
如何用adoquery对一个表中所有列进行模糊查询: procedure TForm3.Button4Click(Sender: TObject); var ASql,AKey: string; I: ...
- SQL查询一个表中类别字段中Max()最大值对应的记录
SQL查询一个表中类别字段中Max()最大值对应的记录 SELECT A.id, A.name, A.version FROM DOC A, (SELECT id, MAX(version) ...
- 如何使用MySQL一个表中的字段更新另一个表中字段
[本文出自:https://www.jb51.net/article/150323.htm] 这篇文章主要介绍了如何使用MySQL一个表中的字段更新另一个表中字段,需要的朋友可以参考下 1,修改1列 ...
- 获取一个表中的字段总数(mysql) Navicat如何导出Excel格式表结构 获取某个库中的一个表中的所有字段和数据类型
如何获取一个表中的字段总数 1.function show columns from 表明: 结果 : 2.functiuon select count(*) from INFORMATION_SCH ...
- sql一个表中两个字段合并求和
sql一个表中两个字段,合并求和 SELECT SUM(字段a+'.'+字段b) as total from TABLE
- mysql从一个表中拷贝数据到另一个表中sql语句
这一段在找新的工作,今天面试时,要做一套题,其中遇到这么一句话,从一个表中拷贝所有的数据到另一个表中的sql是什么? 原来我很少用到,也没注意过这个问题,面试后我上网查查,回来自己亲手写了写,测试了下 ...
- mysql中把一个表的数据批量导入另一个表中
mysql中把一个表的数据批量导入另一个表中 不管是在网站开发还是在应用程序开发中,我们经常会碰到需要将MySQL或MS SQLServer某个表的数据批量导入到另一个表的情况,甚至有时还需要指定 ...
随机推荐
- Python基础部分:7、 垃圾回收机制和流程控制
目录 一.垃圾回收机制 1.引用计数 2.标记清除 3.分类代收 二.流程控制 1.理论 2.必备知识 3.分支结构 4.循环结构 一.垃圾回收机制 垃圾回收机制,简称GC,是python解释器自带的 ...
- Day09:switch——case结构的使用详解
switch--case结构的使用详解 什么是switch--case结构 他也是一种多选择结构 switch--case结构是类于if--else的语法,通过比较而输出对应的内容: 通俗的讲,好比我 ...
- 基于iNeuOS工业互联网平台的板材实时质检系统
1. 项目背景 刨花板生产线由于原料.生产工艺等原因,会有一些产品板面出现颤纹.漏砂.胶斑.胶块.大刨花.粉尘斑.板面划痕和油污等缺陷.表面缺陷会降低板材强度.影响板材外观和二次加工,给企业带来经济 ...
- 数据库可视化工具分享 (DBeaver)
前提:最近公司下发通知,所有开发人员 必须 卸载 Navicat 数据库可视化工具,不知道兄弟们有没有在使用的,可能现在的反应跟我一样,一脸懵逼,Navicat为什么不能使用呢? 有事没事找度娘,于是 ...
- MSP430中断小实验——通过按键改变小灯闪烁频率
本小实验基于MSP430f5529,不同的型号可能管脚和中断配置有所不同. 实现的功能为: 第一次按下按键后,系统以每 2 秒钟,指示灯暗 1 秒,亮 1 秒的方式闪烁.程序采用默认时钟配置: 第二次 ...
- i春秋broken
点开一个附带超链接的网页,直接点击file跳转到broken网页 网页里面是一个jsfuck代码 Jsfuck代码的执行方法 ①复制 ②打开firefox浏览器 ③按下F12 ④选择上方的控制台 ⑤在 ...
- 第1章-Spring的模块与应用场景
目录 一.Spring模块 1. 核心模块 2. AOP模块 3. 消息模块 4. 数据访问模块 5. Web模块 6. 测试模块 二.集成功能 1. 目标原则 2. 支持组件 三.应用场景 1. 典 ...
- easyui combobox的级联设置
<body> <input id="title" class="easyUI-combobox" //onSelect:在该combobox被 ...
- Flink SQL管理平台flink-streaming-platform-web安装搭建
文章都在个人博客网站:https://www.ikeguang.com/ 同步,欢迎访问. 最近看到有人在用flink sql的页面管理平台,大致看了下,尝试安装使用,比原生的flink sql界面确 ...
- “XZ”格式文件解压
1.下载xz 官网:https://tukaani.org/xz/ 例:wget https://nchc.dl.sourceforge.net/project/lzmautils/xz-5.2.6. ...