【SQL边干边学系列】07高级问题-3

文章目录

  • 前言
  • 回顾
  • 高级问题
    • 41.逾期订单
    • 42.逾期订单-哪些员工?
    • 43.逾期订单与总订单相比
    • 44.逾期订单与总订单相比 - 丢失的员工
    • 45.逾期订单与总订单相比 - 修复null
    • 46.逾期订单与总订单之间的百分比
    • 47.逾期订单与总订单相比 - 修正decimal
  • 答案
    • 41.逾期订单
    • 42.逾期订单-哪些员工?
    • 43.逾期订单与总订单相比
    • 44.逾期订单与总订单相比 - 丢失的员工
    • 45.逾期订单与总订单相比 - 修复null
    • 46.逾期订单与总订单之间的百分比
    • 47.逾期订单与总订单相比 - 修正decimal
  • 未完待续


前言

在这里插入图片描述
该系列教程,将会从实际问题出发,边干边学,逐步深入讲解SQL的各方面知识。

你需要完成所有的问题吗?绝对不是。介绍性的问题相当简单,所以你可以直接跳过到“中级问题”部分。如果你不是初学者,但不确定应该从哪里开始,请在“入门问题”部分看看问题和预期结果,并确保你理解这些概念。如果已经理解了这些概念,请开始阅读“中级问题”部分。

你想从这本书中复制代码并在你的服务器上运行?我建议你手动输入,而不是复制粘贴。为什么要去麻烦地重新打字呢?科学表明,打字的行为会在你的脑中留下更深刻的印象。当你只是复制和粘贴时,代码只是直接从你电脑里的一个窗口转到另一个窗口,而不会给你留下多少印象。但是当你把它打出来时,你必须集中精力,这非常有助于保留信息。

一旦你完成了所有的问题,将拥有一些在数据分析和高级Select语句使用方面非常有用的技能。当然,这并不是SQL的全部内容。还有修改数据(更新、插入、删除)、DDL(数据定义语言,即如何创建和修改数据库对象)、编程(如存储过程)和许多其他主题。

该系列教程中,只涉及到了使用Select语句检索数据的问题,这几乎是所有其他数据库主题的基础开端。


回顾

上篇文章👉《【SQL边干边学系列】06高级问题-2》 开始讨论高级问题,这篇我们接着讨论。


高级问题

41.逾期订单

一些客户抱怨他们的订单迟到了。哪些订单迟到了?

-- 预期结果
OrderID     OrderDate  RequiredDate ShippedDate
----------- ---------- ------------ -----------
10264       2014-07-24 2014-08-21   2014-08-23
10271       2014-08-01 2014-08-29   2014-08-30
10280       2014-08-14 2014-09-11   2014-09-12
10302       2014-09-10 2014-10-08   2014-10-09
10309       2014-09-19 2014-10-17   2014-10-23
10380       2014-12-12 2015-01-09   2015-01-16
10423       2015-01-23 2015-02-06   2015-02-24
10427       2015-01-27 2015-02-24   2015-03-03
10433       2015-02-03 2015-03-03   2015-03-04
10451       2015-02-19 2015-03-05   2015-03-12
10483       2015-03-24 2015-04-21   2015-04-25
10515       2015-04-23 2015-05-07   2015-05-23
......
10970 2016-03-24 2016-04-07 2016-04-24
10978 2016-03-26 2016-04-23 2016-04-23
10998 2016-04-03 2016-04-17 2016-04-17
(39 row(s) affected)

提示:要确定哪些订单会延迟,可以组合使用RequiredDate和ShippedDate。如果ShippedDate实际上已经晚于RequiredDate,你可以确定它已经晚了。

42.逾期订单-哪些员工?

有些销售人员逾期的订单比其他人多。也许他们没有跟进订购流程,需要更多的培训。哪些销售人员的订单逾期最多?

-- 预期结果
EmployeeID  LastName             TotalLateOrders
----------- -------------------- ---------------
4           Peacock              10
3           Leverling            5
8           Callahan             5
9           Dodsworth            5
7           King                 4
2           Fuller               4
1           Davolio              3
6           Suyama               3
(8 row(s) affected)

提示:上面这个问题的答案是一个很好的起点。你需和“ Employee”表Join以获得last name,并添加“Count”来显示逾期订单总数。

43.逾期订单与总订单相比

仅仅查看每个销售人员逾期的订单数量并不是一个好主意。它需要与每个销售人员的订单总数进行比较。返回如下结果:

-- 预期结果
EmployeeID  LastName             AllOrders   LateOrders
----------- -------------------- ----------- -----------
1           Davolio              123         3
2           Fuller               96          4
3           Leverling            127         5
4           Peacock              156         10
6           Suyama               67          3
7           King                 72          4
8           Callahan             104         5
9           Dodsworth            43          5
(8 row(s) affected)

提示如下

你可以在一个查询中使用多个CTE。这将是解决这个问题的一种直接的方法。

下面是2个SQL语句,它们可以放入CTE中,并一起放入最终的SQL语句中。

-- Late orders
SelectEmployeeID,TotalOrders = Count(*)
From Orders 
WhereRequiredDate <= ShippedDate
Group ByEmployeeID
-- Total orders
SelectEmployeeID,TotalOrders = Count(*)
From Orders 
Group ByEmployeeID

44.逾期订单与总订单相比 - 丢失的员工

在上面这个问题的答案中缺少了一个员工。修复SQL,以显示所有已接受订单的员工。

-- 预期结果
EmployeeID  LastName              AllOrders  LateOrders
----------- -------------------- ----------- -----------
1           Davolio              123         3
2           Fuller               96          4
3           Leverling            127         5 
4           Peacock              156         10
5           Buchanan             42          NULL
6           Suyama               67          3
7           King                 72          4
8           Callahan             104         5
9           Dodsworth            43          5
(9 row(s) affected)

提示:当你只运行 AllOrders CTE时,返回了多少行?如果你只运行LateOrders CTE,返回了多少行?应该添加一个左连接(也称为左外部连接),以确保我们显示每一行,即使没有逾期订单。

45.逾期订单与总订单相比 - 修复null

继续上面查询的答案,让我们修复第5行的结果。在逾期订单中应该有0而不是null。

-- 预期结果
EmployeeID  LastName              AllOrders  LateOrders
----------- -------------------- ----------- -----------
1           Davolio              123         3
2           Fuller               96          4
3           Leverling            127         5 
4           Peacock              156         10
5           Buchanan             42          0
6           Suyama               67          3
7           King                 72          4
8           Callahan             104         5
9           Dodsworth            43          5
(9 row(s) affected)

提示:找到一个函数来测试一个值是否为空,并在该值为null时返回一个不同的值。

46.逾期订单与总订单之间的百分比

现在我们想知道逾期订单占总订单的比例。

-- 预期结果
EmployeeID  LastName              AllOrders  LateOrders  PercentLateOrders
----------- -------------------- ----------- ----------- -------------------
1           Davolio              123         3           0.0243902439024
2           Fuller               96          4           0.0416666666666
3           Leverling            127         5           0.0393700787401
4           Peacock              156         10          0.0641025641025
5           Buchanan             42          0           0.0000000000000
6           Suyama               67          3           0.0447761194029
7           King                 72          4           0.0555555555555
8           Callahan             104         5           0.0480769230769
9           Dodsworth            43          5           0.1162790697674
(9 row(s) affected)

提示如下

通过将逾期订单除以总订单,应该能够得到百分比。然而,人们会遇到一个常见的问题,即一个整数除以一个整数返回一个整数。例如,如果运行这条SQL:select 3/2,你将得到1而不是1.5,因为它将返回最接近的整数。

47.逾期订单与总订单相比 - 修正decimal

为了使输出更容易读取,我们让百分比字段保留2位小数。

-- 预期结果
EmployeeID  LastName              AllOrders  LateOrders  PercentLateOrders
----------- -------------------- ----------- ----------- -------------------
1           Davolio              123         3           0.02
2           Fuller               96          4           0.04
3           Leverling            127         5           0.04
4           Peacock              156         10          0.06
5           Buchanan             42          0           0.00
6           Suyama               67          3           0.04
7           King                 72          4           0.06
8           Callahan             104         5           0.05
9           Dodsworth            43          5           0.12
(9 row(s) affected)

提示如下

一种简单的方法是显式地将PercentageLateOrders转换为特定的Decimal类型。使用Decimal类型,您可以指定小数点右侧的位数。

计算PercentLateOrders变得有点长和复杂,要使所有的逗号和括号都正确可能很棘手。

简化它的一种方法是用一个实际的值进行验证。例如:

Select convert(decimal(10,2), 0.0243902439024)

答案

41.逾期订单

答案

SelectOrderID ,OrderDate = convert(date, OrderDate),RequiredDate = convert(date, RequiredDate),ShippedDate = convert(date, ShippedDate)
From Orders 
WhereRequiredDate <= ShippedDate

42.逾期订单-哪些员工?

答案

SelectEmployees.EmployeeID,LastName,TotalLateOrders = Count(*)
From Orders Join Employeeson Employees.EmployeeID = Orders.EmployeeID
WhereRequiredDate <= ShippedDate
Group ByEmployees.EmployeeID,Employees.LastName
Order by TotalLateOrders desc

讨论

请注意,“Employees”表中的LastName和EmployeeID都需要包含在Group by子句中,否则我们将得到错误信息。

从技术上讲,EmployeeID是一个主键字段,由于我们已经按其进行分组,只有一个LastName与EmployeeID相关联。但是,数据库引擎并不知道这一点,并且仍然需要在 Group by子句中包含LastName。

43.逾期订单与总订单相比

答案

;With LateOrders as (SelectEmployeeID,TotalOrders = Count(*)From Orders WhereRequiredDate <= ShippedDateGroup ByEmployeeID
)
, AllOrders as (SelectEmployeeID,TotalOrders = Count(*)From Orders Group ByEmployeeID
)
SelectEmployees.EmployeeID,LastName,AllOrders = AllOrders.TotalOrders,LateOrders = LateOrders.TotalOrders
From EmployeesJoin AllOrders on AllOrders.EmployeeID = Employees.EmployeeIDJoin LateOrderson LateOrders.EmployeeID = Employees.EmployeeID

讨论

上面的查询几乎是正确的,但是如果你仔细注意,你会意识到它有一个小问题。我们将在下一个问题中了解到更多信息。

44.逾期订单与总订单相比 - 丢失的员工

答案

;With LateOrders as (SelectEmployeeID,TotalOrders = Count(*)From Orders WhereRequiredDate <= ShippedDateGroup ByEmployeeID
)
, AllOrders as (SelectEmployeeID,TotalOrders = Count(*)From Orders Group ByEmployeeID
)
SelectEmployees.EmployeeID,LastName,AllOrders = AllOrders.TotalOrders,LateOrders = LateOrders.TotalOrders
From EmployeesJoin AllOrders on AllOrders.EmployeeID = Employees.EmployeeIDLeft Join LateOrderson LateOrders.EmployeeID = Employees.EmployeeID

讨论

如果我们展示所有的员工(包括那些没有订单的员工),我们需要使用左连接。

45.逾期订单与总订单相比 - 修复null

答案

;With LateOrders as (SelectEmployeeID,TotalOrders = Count(*)From Orders WhereRequiredDate <= ShippedDateGroup ByEmployeeID
)
, AllOrders as (SelectEmployeeID,TotalOrders = Count(*)From Orders Group ByEmployeeID
)
SelectEmployees.EmployeeID,LastName,AllOrders = AllOrders.TotalOrders,LateOrders = IsNull(LateOrders.TotalOrders, 0)
From EmployeesJoin AllOrders on AllOrders.EmployeeID = Employees.EmployeeIDLeft Join LateOrderson LateOrders.EmployeeID = Employees.EmployeeID

讨论

在LateOrder上直接使用IsNull是解决这个问题的最佳方法。

另一种写方法是使用Case语句:

LateOrders =CaseWhen LateOrders.TotalOrders is null Then 0Else LateOrders.TotalOrdersEnd

但是,当你除了测试null之外不需要任何其他逻辑时,IsNull是最好的方法。

46.逾期订单与总订单之间的百分比

答案

;With LateOrders as (SelectEmployeeID,TotalOrders = Count(*)From Orders WhereRequiredDate <= ShippedDateGroup ByEmployeeID
)
, AllOrders as (SelectEmployeeID,TotalOrders = Count(*)From Orders Group ByEmployeeID
)
SelectEmployees.EmployeeID,LastName,AllOrders = AllOrders.TotalOrders,LateOrders = IsNull(LateOrders.TotalOrders, 0),PercentLateOrders =(IsNull(LateOrders.TotalOrders, 0) * 1.00) / AllOrders.TotalOrders
From EmployeesJoin AllOrders on AllOrders.EmployeeID = Employees.EmployeeIDLeft Join LateOrderson LateOrders.EmployeeID = Employees.EmployeeID

讨论

如果你只是添加一个字段:

PercentLateOrders = LateOrders.TotalLateOrders/AllOrders.TotalOrders

所有字段都会得到0,尽管这显然是不正确的。但这就是当你把两个整数除在一起时所发生的情况。你需要将其中一个转换为decimal。转换为decimal数据类型的一种常见方法是乘以1.00。

请注意,在进行除法之前,你需要将整数转换decimal。如果你在除法之后做,就像这样:

(IsNull(LateOrders.TotalOrders, 0) / AllOrders.TotalOrders) * 1.00

你仍然会得到0。

47.逾期订单与总订单相比 - 修正decimal

答案

;With LateOrders as (SelectEmployeeID,TotalOrders = Count(*)From Orders WhereRequiredDate <= ShippedDateGroup ByEmployeeID
)
, AllOrders as (SelectEmployeeID,TotalOrders = Count(*)From Orders Group ByEmployeeID
)
SelectEmployees.EmployeeID,LastName,AllOrders = AllOrders.TotalOrders,LateOrders = IsNull(LateOrders.TotalOrders, 0),PercentLateOrders =Convert(Decimal (10,2),(IsNull(LateOrders.TotalOrders, 0) * 1.00) / AllOrders.TotalOrders)
From EmployeesJoin AllOrders on AllOrders.EmployeeID = Employees.EmployeeIDLeft Join LateOrderson LateOrders.EmployeeID = Employees.EmployeeID

讨论

四舍五入、截断和转换数据类型可能会变得复杂,而且有很多方法可能获得意想不到的结果。一定要仔细检查你的结果,并知道你是想要舍入,还是想要截断。

你可能已经注意到,我在计算中添加了一些新的行,以使它更容易阅读。这并不是必要的,但这是一种很好的编程实践,它更容易阅读和进行故障排除。


未完待续

下一篇我们接着讲剩余的高级问题。


如果喜欢这篇文章,请不要忘记关注🧡、点赞👍和收藏📔哦!

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

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

相关文章

一文了解localStorage 和 sessionStorage

文章导读&#xff1a;AI 辅助学习前端&#xff0c;包含入门、进阶、高级部分前端系列内容&#xff0c;当前是 JavaScript 的部分&#xff0c;瑶琴会持续更新&#xff0c;适合零基础的朋友&#xff0c;已有前端工作经验的可以不看&#xff0c;也可以当作基础知识回顾。 这篇文章…

Linux - 复盘一次句柄数引发的故障

文章目录 Pre&#xff08;内核、用户、进程&#xff09;句柄数设置问题 shell修复 Pre Linux - 深入理解/proc虚拟文件系统&#xff1a;从基础到高级 &#xff08;内核、用户、进程&#xff09;句柄数设置 在Linux系统中&#xff0c;进程打开的最大句柄数可以通过多种方式配置…

第二证券:大牛股连续七跌停,上市公司坐不住了!机构抄底

6月12日&#xff0c;沪深股市双双飘红。但是&#xff0c;从前的大牛股松炀资源(603863)&#xff0c;却依然跌停收盘。这也是公司股价近日来的接连第七个跌停板。 龙虎榜显现&#xff0c;6月12日&#xff0c;松炀资源全天换手率10.38%&#xff0c;成交额3.45亿元。当天&#xf…

沉降观测点的定义、重要性、建设与选择

沉降观测点&#xff0c;简称沉降点&#xff0c;是指在建筑物、构筑物或地基等结构物上设置的用于测量其垂直位移(沉降)的特定位置。这些点通常被标记并安装相应的监测设备&#xff0c;以便长期、连续地监测结构物的沉降情况。 点击输入图片描述&#xff08;最多30字&#xff09…

炒股的另外一种思路

曾经偶然机会&#xff0c;买了 h 一只股票放了七年左右&#xff0c;不多但是让我看到另外一种投资方法 整个经济中&#xff0c;有些公司是你想去但是可能没机会去的&#xff0c;行业也比较看好&#xff0c;那就选择买他们家股票&#xff0c;因为大概率他们是赢取了市场平均收益…

python接入汇率换算工具提高网站/小程序日活度

实时汇率换算工具可以帮助用户快速准确地计算不同货币之间最新的汇兑比例。无论是金融从业者或者是人们日常生活出行都会使用到&#xff0c;广泛用于国际结算、银行汇率查询应用、开展跨国贸易、投资等参考场景。 我们可以通过在网站或者小程序中接入这样一个小工具&#xff0…

【Ardiuno】实验ESP32单片机自动配置Wifi功能(图文)

这里小飞鱼按照ESP32的示例代码&#xff0c;实验一下wifi的自动配置功能。所谓的自动配置&#xff0c;就是不用提前将wifi的名称和密码写到程序里&#xff0c;这样可以保证程序在烧录上传后&#xff0c;可以通过手机端的软件来进行配置&#xff0c;可以避免反复修改代码&#x…

ChromeOS 逐渐靠近安卓

ChromeOS 逐渐 “安卓化” 谷歌在博客中透露&#xff0c;将在ChromeOS底层更广泛地使用和Android相同的技术栈。一个具体的例子是&#xff0c;ChromeOS现在已经开始使用Android的蓝牙协议栈&#xff0c;取代了之前使用的自己的协议栈。这次改变不仅提高了蓝牙配对速度&#xf…

什么是Rademacher复杂度(Rademacher Complexity)

Rademacher复杂度&#xff08;Rademacher Complexity&#xff09;是在学习理论中用于衡量函数类复杂度的一种工具&#xff0c;特别是在评估机器学习模型泛化能力时。它提供了一种量化学习算法可能过拟合数据的程度的方法。Rademacher复杂度定义了函数类在给定数据集上的随机化复…

Postman下发流表至Opendaylight

目录 任务目的 任务内容 实验原理 实验环境 实验过程 1、打开ODL控制器 2、网页端打开ODL控制页面 3、创建拓扑 4、Postman中查看交换机的信息 5、L2层流表下发 6、L3层流表下发 7、L4层流表下发 任务目的 1、掌握OpenFlow流表相关知识&#xff0c;理解SDN网络中L…

【vue-8】记事本案例

小知识点&#xff1a; 列表末尾插入数据&#xff1a; list.push("lihua") 列表删除数据&#xff1a; # index要删除数据的索引值&#xff0c;1为删除数据长度 list.splice(index,1) 完整示例代码&#xff1a; <!DOCTYPE html> <html lang"en&quo…

Oracle数据库查询常用语句

Oracle数据库查询常用语句 文章目录 Oracle数据库查询常用语句一、时间查询1、查询当天得数据 二、 一、时间查询 1、查询当天得数据 1、字段名为PLAN_DAY&#xff0c;字段类型为DATE 使用SYSDATE函数来获取当前日期&#xff0c;并且使用比较运算符来过滤出当天的记录。Oracle…

R语言ggHoriPlot包绘制地平线图

数据和代码获取&#xff1a;请查看主页个人信息&#xff01;&#xff01;&#xff01; 关键词“地平线图” 1. 数据读取与处理 首先&#xff0c;从TSV文件中读取数据&#xff0c;并进行数据清洗和处理。 rm(listls()) pacman::p_load(tidyverse,ggalt,ggHoriPlot,hrbrthemes…

教程:A5000 GPU 上运行阿里最新开源大模型 Qwen2

这是我们新一篇关于大模型的文章&#xff0c;我们此前还讲过如何运行 LLama3 大模型。而这次&#xff0c;我们将使用 Ollama 运行阿里千问Qwen2:7b。要知道 Qwen2 可是目前最热门的开源大语言模型了&#xff0c;甚至在一些性能测试中比 LLama3 表现还突出。谁不想试试看呢&…

创建FileInputStream对象不使用filePath,而是用字节流数组,怎么改

改之前 fileInputStream new FileInputStream(new File(filePath)); fileReader new PdfReader(fileInputStream); fileDocunment new PdfDocument(fileReader);改之后 如果你有一个字节流数组&#xff08;byte array&#xff09;而不是文件的路径&#xff0c;并且你想要使…

C#下WinForm多语种切换

这是应一个网友要求写的&#xff0c;希望对你有所帮助。本文将介绍如何在一个WinForm应用程序中实现多语种切换。通过一个简单的示例&#xff0c;你将了解到如何使用资源文件管理不同语言的文本&#xff0c;并通过用户界面实现语言切换。 创建WinForm项目 打开Visual Studio&a…

最新下载:XmanagerXShell【软件附加安装教程】

​XManager企业版是一款完整的企业网络连接套件&#xff0c;它配备了一个高性能的PC服务器&#xff0c;安全终端模拟器&#xff0c;是一个一体化的解决方案&#xff0c;将xmanager&#xff0c;xshell&#xff0c;xftp&#xff0c;xlpd&#xff0c;Xbrowser及xstart放置在一个软…

代码随想录算法训练营DAY37| 56. 合并区间、738.单调递增的数字、968.监控二叉树、总结

56.合并区间 题目链接&#xff1a;56. 合并区间 class Solution(object):def merge(self, intervals):""":type intervals: List[List[int]]:rtype: List[List[int]]"""intervals.sort(key lambda x:x[0])i0while i<len(intervals)-1:if i…

C#发送邮件

C#发送邮件代码&#xff0c;亲测可用。 using System; using System.Net; using System.Net.Mail;namespace MailSend {class Program{static void Main(string[] args){try{MailAddress receiver new MailAddress("666666666qq.com");//666666666qq.com 换成收件人…

前端面试题日常练-day66 【面试题】

题目 希望这些选择题能够帮助您进行前端面试的准备&#xff0c;答案在文末 TypeScript中&#xff0c;以下哪个关键字用于声明一个类的静态属性或方法&#xff1f; a) static b) const c) let d) final 在TypeScript中&#xff0c;以下哪个符号用于声明一个变量的类型为任意类…