SQL练习【个人练习】

SQL练习, 去除了过于简单的SQL语句

  • 常用函数的使用
    • concat&substring
    • like&left切割&正则比较&时间函数(date_format/year/month)
    • 时间函数匹配
  • group by
  • 子查询
  • Union

前几天做笔试的时候狠狠拷打了SQL,并不是很难的题目,现在想起来感觉当时真的呆, 写完就知道笔试没希望了😭😭🤡,平时被MP惯坏了, 很少写SQL, 导致语法都生疏了, 所以花一天时间把100多道SQL刷完了, 下面是一些我觉得还不错的题(我不会的🤪)。
题目来源是牛客网 SQL必知必会,牛客上的题出的不错但是重复题型很多, 其实一类题刷一道后面就知道怎么写了

常用函数的使用

concat&substring

我们的商店已经上线了,正在创建顾客账户。所有用户都需要登录名,默认登录名是其名称和所在城市的组合。

给出 Customers表 如下:

cust_idcust_namecust_contactcust_city
a1Andy LiAndy LiOak Park
a2Ben LiuBen LiuOak Park
a3Tony DaiTony DaiOak Park
a4Tom ChenTom ChenOak Park
a5An LiAn LiOak Park
a6Lee ChenLee ChenOak Park
a7Hex LiuHex LiuOak Park

【问题】编写 SQL 语句,返回顾客 ID(cust_id)、顾客名称(cust_name)和登录名(user_login),其中登录名全部为大写字母,并由顾客联系人的前两个字符(cust_contact)和其所在城市的前三个字符(cust_city)组成。提示:需要使用函数、拼接和别名。

【示例结果】

返回顾客id cust_id,顾客名称cust_name,顾客登录名 user_login

cust_idcust_nameuser_login
a1Andy LiANOAK
a2Ben LiuBEOAK
a3Tony DaiTOOAK
a4Tom ChenTOOAK
a5An LiANOAK
a6Lee ChenLEOAK
a7Hex LiuHEOAK

【示例解析】

例如,登录名是 ANOAK(Andy Li,居住在 Oak Park)

  • SQL中的substring都是闭区间, 且下标从1开始
select cust_id, cust_name, upper(concat(substring(cust_name, 1, 2), substring(cust_city,1,3))) as user_login
from Customers;

like&left切割&正则比较&时间函数(date_format/year/month)

Orders订单表

order_numorder_date
a00012020-01-01 00:00:00
a00022020-01-02 00:00:00
a00032020-01-01 12:00:00
a00042020-02-01 00:00:00
a00052020-03-01 00:00:00

【问题】编写 SQL 语句,返回 2020 年 1 月的所有订单的订单号(order_num)和订单日期(order_date),并按订单日期升序排序

【示例结果】

返回订单号order_num,和order_date订单时间

order_numorder_date
a00012020-01-01 00:00:00
a00032020-01-01 12:00:00
a00022020-01-02 00:00:00

【示例解析】

a0001、a0002、a0003 时间属于2020年1月

用like来查找

select order_num, order_date``from Orders``where order_date like ``'2020-01%'``order by order_date

切割字符串

select order_num, order_date``from Orders``where left(order_date, ``7``) = ``'2020-01'``order by order_date

字符串比较

select *``from Orders``where order_date >= ``'2020-01-01 00:00:00'` `and order_date <= ``'2020-01-31 23:59:59'``order by order_date;

用正则来查找(效率不如like,能用like就用like)

select order_num, order_date``from Orders``where order_date regexp ``'2020-01'``order by order_date

时间函数匹配

select order_num, order_date``from Orders``where year(order_date) = ``'2020'` `and month(order_date) = ``'1'``order by order_date

利用date_format函数 (参考其中的匹配规则进行匹配)

select order_num, order_date``from Orders``where date_format(order_date, ``'%Y-%m'``)=``'2020-01'``order by order_date

group by

group by经常和一些聚合函数一起使用的, 比如MAX, MIN, Count这些

OrderItems 表包含每个订单的每个产品

order_num
a002
a002
a002
a004
a007

【问题】编写 SQL 语句,返回每个订单号(order_num)各有多少行数(order_lines),并按 order_lines对结果进行升序排序。

【示例结果】返回订单号order_num和对应订单号的行数order_lines

order_numorder_lines
a0041
a0071
a0023

【示例解析】

订单号a002有3行订单记录也是最多的订单号故排在最后一位返回,相同订单行数的订单无需过多处理。

select order_num, count(order_num) as order_lines
from OrderItems
group by order_num
order by order_lines

这道题容易出错的的点:

  • 注意要写出group by order_num, 聚合函数配套group by不然没办法做出分组效果
  • image-20240325205247256

SQL关键字顺序总结:

(1) FROM: 对FROM子句中的左表<left_table>和右表<right_table>执行笛卡儿积,产生虚拟表VT1;
(2) ON: 对虚拟表VT1进行ON筛选,只有那些符合<join_condition>的行才被插入,产生虚拟表VT2;
(3) JOIN: 如果指定了OUTER JOIN(如LEFT OUTER JOIN、RIGHT OUTER JOIN),那么保留表中未匹配的行作为外部行添加到虚拟表VT2,产生虚拟表VT3。如果FROM子句包含两个以上的表,则对上一个连接生成的结果表VT3和下一个表重复执行步骤1~步骤3,直到处理完所有的表;
(4) WHERE: 对虚拟表VT3应用WHERE过滤条件,只有符合<where_condition>的记录才会被插入到VT4;
(5) GROUP By: 根据GROUP BY子句中的列,对VT4中的记录进行分组操作,产生VT5;
(6) CUBE|ROllUP: 对VT5进行CUBE或ROLLUP操作,产生VT6;
(7) HAVING: 对虚拟表VT6应用HAVING过滤器,只有符合<having_condition>的记录才会被插入到VT7;
(8) SELECT: 第二次执行SELECT操作,选择指定的列,插入到虚拟表VT8中;
(9) DISTINCT: 去除重复,得到虚拟表VT9;
(10) ORDER BY: 将虚拟表VT9中的记录按照<order_by_list>进行排序操作,得到虚拟表VT10;
(11) LIMIT: 取出指定行的记录,产生虚拟表VT11,并返回给查询用户

有Products表,含有字段prod_price代表产品价格,vend_id代表供应商id

vend_idprod_price
a0011100
a00190.1
b00191000
b00196980
b001920

【问题】编写 SQL 语句,返回名为 cheapest_item 的字段,该字段包含每个供应商成本最低的产品(使用 Products 表中的 prod_price),然后从最低成本到最高成本对结果进行升序排序。

【示例结果】返回供应商id vend_id和对应供应商成本最低的产品cheapest_item。

vend_idcheapest_item
a00190.1
b001920
a0011100

【示例解析】

例如b0019成本最低的价格是20,且最后根据成本价格排序返回依次是a0019、b0019、a0011。

select vend_id, min(prod_price) as cheapest_item
from Products
group by vend_id
order by cheapest_item;

OrderItems代表订单商品表,包括:订单号order_num和订单数量quantity。

order_numquantity
a1105
a21100
a2200
a41121
a510
a219
a75

【问题】请编写 SQL 语句,返回订单数量总和不小于100的所有订单号,最后结果按照订单号升序排序。

【示例结果】返回order_num订单号。

order_num
a1
a2
a4

【示例解析】

订单号a1、a2、a4的quantity总和都大于等于100,按顺序为a1、a2、a4。

select distinct(order_num)
from OrderItems
where quantity > 100
order by order_num
  • where 子句的作用是在对查询结果进行分组前,将不符合where条件的行去掉,即在分组之前过滤数据,where条件中不能包含聚组函数,使用where条件过滤出特定的行。
  • having 子句的作用是筛选满足条件的组,即在分组之后过滤数据,条件中经常包含聚组函数,使用having 条件过滤出特定的组,也可以使用多个分组标准进行分组。
# 直接使用聚合
select order_num
from OrderItems
group by order_num
having  sum(quantity) >= 100
order by order_num

子查询

什么叫做子查询

  • 子查询是在主查询前面就得到结果的查询, 一般子查询的结果被主查询使用, 而且一般用括号括起来~

OrderItems表示订单商品表,含有字段订单号:order_num、订单价格:item_price;Orders表代表订单信息表,含有顾客id:cust_id和订单号:order_num

OrderItems表

order_numitem_price
a110
a21
a21
a42
a55
a21
a77

Orders表

order_numcust_id
a1cust10
a2cust1
a2cust1
a4cust2
a5cust5
a2cust1
a7cust7

【问题】使用子查询,返回购买价格为 10 美元或以上产品的顾客列表,结果无需排序。
注意:你需要使用 OrderItems 表查找匹配的订单号(order_num),然后使用Order 表检索这些匹配订单的顾客 ID(cust_id)。

【示例结果】返回顾客id cust_id

cust_id
cust10

【示例解析】

cust10顾客下单的订单为a1,a1的售出价格大于等于10

# 子查询
select cust_id from Orders
where order_num IN (select order_numfrom OrderItemswhere item_price>=10
)
#关联查询
select o.cust_id
from Orders as o
inner join OrderItems as ot
on o.order_num=ot.order_num and ot.item_price >=10

表OrderItems代表订单商品信息表,prod_id为产品id;Orders表代表订单表有cust_id代表顾客id和订单日期order_date

OrderItems表

prod_idorder_num
BR01a0001
BR01a0002
BR02a0003
BR02a0013

Orders表

order_numcust_idorder_date
a0001cust102022-01-01 00:00:00
a0002cust12022-01-01 00:01:00
a0003cust12022-01-02 00:00:00
a0013cust22022-01-01 00:20:00

【问题】

编写 SQL 语句,使用子查询来确定哪些订单(在 OrderItems 中)购买了 prod_id 为 “BR01” 的产品,然后从 Orders 表中返回每个产品对应的顾客 ID(cust_id)和订单日期(order_date),按订购日期对结果进行升序排序。

【示例结果】返回顾客id cust_id和定单日期order_date。

cust_idorder_date
cust102022-01-01 00:00:00
cust12022-01-01 00:01:00

【示例解析】

产品id为"BR01"的订单a0001和a002的下单顾客cust10和cust1的下单时间分别为2022-01-01 00:00:00和2022-01-01 00:01:00

子查询

select cust_id, order_date from Orders
where order_num in (select order_num from OrderItems where prod_id='BR01')
外连接
select cust_id,order_date
from Orders
left join OrderItems on OrderItems.order_num = Orders.order_num
where OrderItems.prod_id='BR01'

OrderItems表代表订单信息,确定最佳顾客的另一种方式是看他们花了多少钱,OrderItems表有订单号order_num和item_price商品售出价格、quantity商品数量

order_numitem_pricequantity
a110105
a211100
a21200
a421121
a5510
a2119
a775

Orders表含有字段order_num 订单号、cust_id顾客id

order_numcust_id
a1cust10
a2cust1
a3cust2
a4cust22
a5cust221
a7cust2217

顾客表Customers有字段cust_id 客户id、cust_name 客户姓名

cust_idcust_name
cust10andy
cust1ben
cust2tony
cust22tom
cust221an
cust2217hex

【问题】编写 SQL 语句,返回订单总价不小于1000 的客户名称和总额(OrderItems 表中的order_num)。

提示:需要计算总和(item_price 乘以 quantity)。按总额对结果进行排序,请使用INNER JOIN 语法。

【示例结果】

cust_nametotal_price
andy1050
ben1319
tom2242

【示例解析】

总额(item_price 乘以 quantity)大于等于1000的订单号,例如a2对应的顾客id为cust1,cust1的顾客名称cust_name是ben,最后返回ben作为order_num a2的quantity * item_price总和的结果1319。

SELECT c.cust_name,tb.total_price
FROMCustomers cINNER JOIN Orders oON c.cust_id = o.cust_idINNER JOIN(SELECT order_num,SUM(item_price*quantity) AS total_priceFROM OrderItemsGROUP BY order_numHAVING total_price >= 1000) tbON tb.order_num = o.order_numORDER BY tb.total_price ASC;
select c.cust_name,sum(oi.item_price*oi.quantity) total_price
from OrderItems oi,Orders o,Customers c
where oi.order_num=o.order_num and o.cust_id=c.cust_id
group by c.cust_name
having total_price>=1000
order by total_price;
  • 很特别的using

Products表为产品信息表含有字段prod_id产品id、prod_name产品名称

prod_idprod_name
a0001egg
a0002sockets
a0013coffee
a0003cola
a0023soda

OrderItems表为订单信息表含有字段order_num订单号和产品id prod_id

prod_idorder_num
a0001a105
a0002a1100
a0002a200
a0013a1121
a0003a10
a0003a19
a0003a5

【问题】

使用 OUTER JOIN 联结 Products 表和 OrderItems 表,返回产品名称(prod_name)和与之相关的订单号(order_num)的列表,并按照产品名称升序排序。

【示例结果】

返回产品名称prod_name和订单号order_num

prod_nameorder_num
coffeea1121
colaa5
colaa19
colaa10
egga105
socketsa200
socketsa1100
sodaNULL

【示例解析】

返回产品和对应实际支付订单的订单号,但是无实际订单的产品soda也返回,最后根据产品名称升序排序。

使用using必须满足如下两个条件:

  1. 查询必须是等值连接。

  2. 等值连接中的列必须具有相同的名称和数据类型。

select prod_name,order_num
from Products
left join OrderItems using(prod_id)
order by prod_name

另外一种解法

(
select a.prod_name,  b.order_num 
from Products aleft join  OrderItems b 
on a.prod_id = b.prod_id)
union
(
select a.prod_name,  b.order_num 
from Products aright join  OrderItems b 
on a.prod_id = b.prod_id)

Union

表OrderItems包含订单产品信息,字段prod_id代表产品id、quantity代表产品数量

prod_idquantity
a0001105
a0002100
a0002200
a00131121
a000310
a000319
a00035
BNBG10002

【问题】

将两个 SELECT 语句结合起来,以便从 OrderItems表中检索产品 id(prod_id)和 quantity。其中,一个 SELECT 语句过滤数量为 100 的行,另一个 SELECT 语句过滤 id 以 BNBG 开头的产品,最后按产品 id 对结果进行升序排序。

【示例结果】

返回产品id prod_id和产品数量quantity

prod_idquantity
a0002100
BNBG10002

【示例解析】

产品id a0002因为数量等于100被选取返回;BNBG因为是以 BNBG 开头的产品所以返回;最后以产品id进行排序返回。

  • 这里要区分union和join
  • join—连接表,对列操作
  • union–连接表,对行操作。
    • union–将两个表做行拼接,同时自动删除重复的行。
    • union all—将两个表做行拼接,保留重复的行。
      • 注意使用union的时候, 只能有一个order by
select prod_id,quantity
from OrderItems
where quantity=100
union 
select prod_id,quantity
from OrderItems
where prod_id like 'BNBG%'
order by prod_id;
  • 投机取巧一下 : 直接使用or
select prod_id,quantity from OrderItems
where  quantity=100 or prod_id like 'BNBG%'
order by prod_id;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/568556.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

leetcode 225.用队列实现栈 JAVA

题目 思路 1.一种是用双端队列&#xff08;Deque&#xff09;&#xff0c;直接就可以调用很多现成的方法&#xff0c;非常方便。 2.另一种是用普通的队列&#xff08;Queue&#xff09;,要实现栈的先入后出&#xff0c;可以将最后一个元素的前面所有元素出队&#xff0c;然后…

机器学习基础——模型评估与选择(部分)

为了实现对模型指导&#xff0c;实现自主建模&#xff0c;我们会对模型进行选择和评估&#xff0c;主要有以下几个问题&#xff1a; 一、前言&#xff1a;误差与拟合 &#xff08;一&#xff09;经验误差 使用上述流程理解&#xff0c;其中 a 为预测错误的个数&#xff0c;m为…

【Rust】——提取函数消除重复代码和泛型

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…

工时表软件:项目管理的效率利器

在当今的项目管理实践中&#xff0c;时间是最宝贵的资产之一。精准地追踪和管理项目工时对于项目的成功至关重要。工时表软件作为一种现代管理工具&#xff0c;其应用不仅简化了项目管理流程&#xff0c;还提高了工作效率&#xff0c;已成为现代企业管理不可或缺的一项利器。 …

深入解析ECC(椭圆曲线密码学)加解密算法

码到三十五 &#xff1a; 个人主页 心中有诗画&#xff0c;指尖舞代码&#xff0c;目光览世界&#xff0c;步履越千山&#xff0c;人间尽值得 ! 本文将详细介绍ECC&#xff08;椭圆曲线密码学&#xff09;加解密算法的原理、特点及应用。ECC作为一种新型的公钥密码体制&#…

FL Studio21.2.3最新中文编曲音乐制作软件新版本功能介绍

一、前言 随着科技的发展&#xff0c;越来越多的人开始尝试自己创作音乐。然而&#xff0c;传统的音乐制作过程复杂繁琐&#xff0c;需要昂贵的硬件设备和专业的知识技能。那么&#xff0c;有没有一款软件可以让普通人也能轻松地制作出专业级别的音乐作品呢&#xff1f;答案就…

【优选算法】专题1 -- 双指针 -- 复写0

前言&#xff1a; 补充一下前文没有写到的双指针入门知识&#xff1a;专题1 -- 双指针 -- 移动零 目录 基础入门知识&#xff1a; 1. 复写零&#xff08;easy&#xff09; 1. 题⽬链接&#xff1a;1089.复习0 - 力扣&#xff08;LeetCode&#xff09; 2. 题⽬描述&#xff…

C++ primer 第十五章

1.OPP:概述 面向对象程序设计的核心思想是数据抽象、继承和动态绑定。 通过继承联系在一起的类构成一种层次关系&#xff0c;在层次关系的根部的是基类&#xff0c;基类下面的类是派生类 基类负责定义在层次关系中所有类共同拥有的成员&#xff0c;而每个派生类定义各自特有…

词曲创作只需几秒,「AI作曲家」Suno引爆音乐圈,第一手体验和攻略来了

ChatGPT狂飙160天&#xff0c;世界已经不是之前的样子。 新建了人工智能中文站https://ai.weoknow.com 每天给大家更新可用的国内可用chatGPT资源 发布在https://it.weoknow.com 更多资源欢迎关注 有了 Suno 这个「作曲助手」&#xff0c;人人都可以创建自己想听的歌曲。 自…

使用Appium进行移动应用UI自动化

1. 背景介绍 移动应用的发展与普及日益迅速&#xff0c;其中大部分应用程序需要进行UI自动化测试。Appium是一个开源的移动应用自动化框架&#xff0c;它支持Android、iOS等多种平台&#xff0c;可以用于自动化测试移动应用程序的UI。本文将介绍如何使用Appium进行移动应用UI自…

Landsat 8 Landsat8 Collection2大气层顶反射率数据

简介 Landsat8 TOA数据集是将数据每个波段的辐射亮度值转换为大气层顶表观反射率TOA&#xff0c;是飞行在大气层之外的航天传感器量测的反射率&#xff0c;包括了云层、气溶胶和气体的贡献&#xff0c;可通过辐射亮度定标参数、太阳辐照度、太阳高度角和成像时间等几个参数计算…

C++函数模板详解(结合代码)

目录 1. 模板概念 2. 函数模板语法 3. 函数模板注意事项 4. 函数模板案例 5. 普通函数与函数模板的区别 6. 普通函数与函数模板的调用规则 7. 模板的局限性 1. 模板概念 在C中&#xff0c;模板是一种通用的程序设计工具&#xff0c;它允许我们处理多种数据类型而不是固…