首页 > 数据库 >MySQL union 和 order by 同时使用

MySQL union 和 order by 同时使用

时间:2022-11-11 23:55:07浏览次数:68  
标签:01 pv union uv order MySQL id

目录

一、出现错误的情况

(1)使用 union 和 多个order by 不加括号 报错

(2)order by 在 union 连接的子句不起作用

二、解决上述问题的两种方法

(1)order by 在 union 连接的子句的子句中使用

(2)先使用 union 后使用order by

三、案例分析:

我们举个例子进行说明,案例来自: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。

求解:

分析思路

难点:

1.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降序]
)

常见的错误解法

(1)使用 union 和 多个order by 不加括号 【报错】

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

执行出错

程序异常退出, 请检查代码"是否有数组越界等异常"或者"是否有语法错误"

SQL_ERROR_INFO: "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'union all\n\nselect \n question_id as tid,\n count(distinct uid) as uv,\n co' at line 11"

这是因为union在没有括号的情况下只能有一个order by。为什么只能有一个order by 呢?

既然不加括号出错,那我就加上括号使用2个order by !

(2)order by 在 union 子句中不起作用

(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)
union
(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)

结果发现这样写order by在每个子表中不起作用!所以这种方法也不对。但是 union 可以在子句的子句中起作用,写成下面这样:

正确解法

方法一:

(1)order by 在 union 连接的子句的子句中使用

#正确代码
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个表分别进行降序,就需要写成下面这样:

方法二:

(2)先使用 union 后使用order by

使用函数

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

推荐使用方法一,更具有普适性。

标签:01,pv,union,uv,order,MySQL,id
From: https://www.cnblogs.com/chengyj/p/16882476.html

相关文章

  • MySQL的一些认知
    MyISAM与InnoDBMyISAM的优点:1.快速查询唯一键2.支持全文索引3.选择count(*)速度快4.磁盘空间占用较少缺点:1.表级别的锁定,运用程序写入时间大于5%,表锁定会降低运用程序速度2.......
  • MySQL常用函数
    MySQL数值型函数函数名称作 用ABS求绝对值SQRT求二次方根MOD求余数CEIL和 CEILING两个函数功能相同,都是返回不小于参数的最小整数,即向上取整FLOOR向下取整,返回值转化为......
  • MySQL主键索引和二级索引
    Mysql的索引首先,我们常说的索引类型有:主键索引、唯一索引、普通索引、前缀索引、全文索引,甚至还有聚簇索引、覆盖索引等。其中,唯一索引、普通索引、前缀索引等索引属于......
  • MySQL索引
    MySQL索引是一种帮助快速查找数据的数据结构,通过索引能够快速找到数据所在位置。场景的索引数据结构有:Hash表(通过hash算法快速定位数据,但不适合范围查询,因为需要每个key都......
  • 【转】Mysql分表和分区的区别
     一,什么是mysql分表,分区 什么是分表,从表面意思上看呢,就是把一张表分成N多个小表,具体请看mysql分表的3种方法 什么是分区,分区呢就是把一张表的数据分成N多个区块,这些区块......
  • 插入MySQL报错‘pymysql.err.DataError: (1406, "Data too long for column 'url' at
    错误重现:插入MySQL报错‘pymysql.err.DataError:(1406,"Datatoolongforcolumn'url'atrow1")’解决方法:在插入MySQL的字符太多,此时将MySQL的模式改为非严格模......
  • 2010 Principles on the Security of AES against First and Second-Order Differenti
    一、对于AES算法的DPA攻击准则(无防护措施下的AES实现)(1)在第3轮列混淆前任意中间值可以用于一阶DPA攻击,该攻击将明文的0,3或15比特固定(2)在第7轮轮......
  • mysql判断主从状态
    参考:https://blog.csdn.net/bigtree_3721/article/details/76735214?locationNum=5&fps=1showslavestatus\G会显示主从同步状态例如MySQL>showslavestatus\G***......
  • MySQL中重复数据清理(清理主键Id较小的)
    DELETEFROMuserWHEREidIN(SELECTmin(id)idFROM(SELECT*FROMuserWHERE`member_id`IN(SELECTmember_idFROM(......
  • mysql部署
    #!/bin/bash#定义相关变量MYSQL_DOWNLOAD_PATH=/usr/local/srcMYSQL_URL=https://mirrors.tuna.tsinghua.edu.cn/mysql/downloads/MySQL-5.7/mysql-5.7.38-linux-glibc2.......