【SQL边干边学系列】08高级问题-4

news2024/11/24 16:54:05

文章目录

  • 前言
  • 回顾
  • 高级问题
    • 48.客户分组
    • 49.客户分组-修复null
    • 50.使用百分比的客户分组
    • 51.灵活的客户分组
  • 答案
    • 48.客户分组
    • 49.客户分组-修复null
    • 50.使用百分比的客户分组
    • 51.灵活的客户分组
  • 未完待续


前言

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

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

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

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

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


回顾

上篇文章👉《【SQL边干边学系列】07高级问题-3》 讲了部分高级问题,这篇接着讨论更多的高级问题。


高级问题

48.客户分组

假如想为现有客户做一个销售活动。希望想根据客户在2016年的订购量,将他们分组。然后,根据客户所在的群组,采用不同的销售材料。

客户分组类别为0到1000、1000到5000、5000到10000个,以及超过10000个。

这个查询的一个很好的起点是来自“高价值客户-总订单”这个问题的答案。我们不想展示2016年没有任何订单的客户。

按CustomerID对结果排序。

-- 预期结果
CustomerID CompanyName                        TotalOrderAmount CustomerGroup
---------- ---------------------------------- ---------------- -------------
ALFKI      Alfreds Futterkiste                2302.20          Medium
ANATR      Ana Trujillo Emparedados y helados 514.40           Low
ANTON      Antonio Moreno Taquería            660.00           Low
...
WHITC White Clover Markets 15278.90 Very High
WILMK Wilman Kala 1987.00 Medium
WOLZA Wolski Zajazd 1865.10 Medium
(81 row(s) affected)

提示如下

这是来自“高价值客户-总订单”问题的SQL,但没有针对订单总数超过10,000个的过滤器。

Select
 Customers.CustomerID
 ,Customers.CompanyName
 ,TotalOrderAmount = SUM(Quantity * UnitPrice)
From Customers
 Join Orders
 on Orders.CustomerID = Customers.CustomerID
 Join OrderDetails
 on Orders.OrderID = OrderDetails.OrderID
Where
  OrderDate >= '20160101'
 and OrderDate < '20170101'
Group By
 Customers.CustomerID
 ,Customers.CompanyName
Order By TotalOrderAmount Desc;

你可以在CTE(common table expression)中使用上面的SQL,然后在“TotalOrderAmount”上使用Case语句。

49.客户分组-修复null

上一个问题的答案有一个错误。CustomerGroup中有一行的值为null。

修复SQL,使CustomerGroup字段中没有null。

-- 预期结果
CustomerID CompanyName                     TotalOrderAmount      CustomerGroup
---------- ------------------------------- --------------------- -------------
LILAS      LILA-Supermercado               5994.06               High
LINOD      LINO-Delicateses                10085.60              Very High
LONEP      Lonesome Pine Restaurant        1709.40               Medium
...

提示如下

CustomerID为MAISD的总订单量是多少?这与我们的CustomerGroup边界有何关系?

使用“between”很适合整数值。然而,我们正在分析的字段是Money,它有小数位。因此不能使用下面的SQL:

when TotalOrderAmount between 0 and 1000 then 'Low'

而应该使用下面的SQL:

when TotalOrderAmount >= 0 and TotalOrderAmount < 1000 then 'Low'

50.使用百分比的客户分组

根据上面的查询,显示所有已定义的客户组,以及每个组中的百分比。按每一组的总数排序,按降序排序。

-- 预期结果
CustomerGroup TotalInGroup PercentageInGroup
------------- ------------ ---------------------------------------
Medium        35           0.432098765432
Low           20           0.246913580246
High          13           0.160493827160
Very High     13           0.160493827160
(4 row(s) affected)

提示如下

作为起点,你可以使用问题“客户分组-修复null”中的答案。

我们不再需要在最终的输出中显示CustomerID和CompanyName。但是,我们需要计算每个CustomerGrouping组中有多少客户。你可以创建另一个CTE级别,以便获得最终输出的每个CustomerGrouping中的计数。

51.灵活的客户分组

我们希望根据客户订购的金额来完全灵活地分组。我们不想为了更改客户组的边界而不得不编辑SQL。

你需要一个叫做客户组阈值的表(CustomerGroupThreshold),仅使用从2016年开始的订单。

-- 预期结果
CustomerID CompanyName                        TotalOrderAmount CustomerGroupName
---------- ---------------------------------- ---------------- --------------------
ALFKI     Alfreds Futterkiste                 2302.20          Medium
ANATR     Ana Trujillo Emparedados y helados  514.40           Low
ANTON     Antonio Moreno Taquería             660.00           Low
...
WHITC     White Clover Markets                15278.90         Very High
WILMK     Wilman Kala                         1987.00          Medium
WOLZA     Wolski Zajazd                       1865.10          Medium
(81 row(s) affected)

作为起点,使用问题“使用百分比的客户分组”中的第一个CTE语句

Select
 Customers.CustomerID
 ,Customers.CompanyName
 ,TotalOrderAmount = SUM(Quantity * UnitPrice)
From Customers
 join Orders
 on Orders.CustomerID = Customers.CustomerID
 join OrderDetails
 on Orders.OrderID = OrderDetails.OrderID
Where
 OrderDate >= '20160101'
 and OrderDate < '20170101'
Group By
 Customers.CustomerID
 ,Customers.CompanyName

提示:当考虑如何使用CustomerGroupThreshold表时,请注意,当连接到一个表时,你不仅可以使用一个等值连接(=),还可以使用其他操作符,如between、>或< 。


答案

48.客户分组

答案

;with Orders2016 as (
 Select
 Customers.CustomerID
 ,Customers.CompanyName
 ,TotalOrderAmount = SUM(Quantity * UnitPrice)
 From Customers
 Join Orders
 on Orders.CustomerID = Customers.CustomerID
 Join OrderDetails
 on Orders.OrderID = OrderDetails.OrderID
 Where
 OrderDate >= '20160101'
 and OrderDate < '20170101'
 Group by
 Customers.CustomerID
 ,Customers.CompanyName
)
Select
 CustomerID
 ,CompanyName
 ,TotalOrderAmount
 ,CustomerGroup =
 Case
 when TotalOrderAmount between 0 and 1000 then 'Low'
 when TotalOrderAmount between 1001 and 5000 then 'Medium'
 when TotalOrderAmount between 5001 and 10000 then 'High'
 when TotalOrderAmount > 10000 then 'Very High'
 End
from Orders2016
Order by CustomerID

讨论

CTE很适合解决这个问题,但这并不是严格必要的。你也可以使用这样的SQL:

Select
 Customers.CustomerID
 ,Customers.CompanyName
 ,TotalOrderAmount = SUM(Quantity * UnitPrice)
 ,CustomerGroup =
 Case
 when SUM(Quantity * UnitPrice) between 0 and 1000 then 'Low'
 when SUM(Quantity * UnitPrice) between 1001 and 5000 then 'Medium'
 when SUM(Quantity * UnitPrice) between 5001 and 10000 then 'High'
 when SUM(Quantity * UnitPrice) > 10000 then 'Very High'
 End
From Customers
 Join Orders
   on Orders.CustomerID = Customers.CustomerID
 Join OrderDetails
   on Orders.OrderID = OrderDetails.OrderID
Where
 OrderDate >= '20160101'
 and OrderDate < '20170101'
Group By
 Customers.CustomerID
 ,Customers.CompanyName

这给出了相同的结果,但请注意,TotalOrderAmount被重复了5次,包括Case语句中的4次。

最好避免重复这样的计算。这些计算结果通常会非常复杂和难以阅读,而且你只想把它们放在一个地方。在一些简单的情况下,比如 Quantity * UnitPrice,这并不一定是一个问题。但大多数时候,你应该避免重复任何计算和代码。记住——“不要重复你自己”。

49.客户分组-修复null

答案

;with Orders2016 as (
 Select
 Customers.CustomerID
 ,Customers.CompanyName
 ,TotalOrderAmount = SUM(Quantity * UnitPrice)
 From Customers
 Join Orders
 on Orders.CustomerID = Customers.CustomerID
 Join OrderDetails
 on Orders.OrderID = OrderDetails.OrderID
 Where
 OrderDate >= '20160101'
 and OrderDate < '20170101'
 Group by
 Customers.CustomerID
 ,Customers.CompanyName
)
Select
 CustomerID
 ,CompanyName
 ,TotalOrderAmount
 ,CustomerGroup =
 case
   when TotalOrderAmount >= 0 and TotalOrderAmount < 1000 then 'Low'
   when TotalOrderAmount >= 1000 and TotalOrderAmount < 5000 then 'Medium'
   when TotalOrderAmount >= 5000 and TotalOrderAmount <10000 then 'High'
   when TotalOrderAmount >= 10000 then 'Very High'
 end
from Orders2016
Order by CustomerID

讨论

正如你在上述问题中所看到的那样,了解你正在处理的数据类型以及理解它们之间的差异对于获得正确的结果非常重要。使用“between”对于整数值就可以,但对于Money则不行。

50.使用百分比的客户分组

答案

;with Orders2016 as (
 Select
   Customers.CustomerID
   ,Customers.CompanyName
   ,TotalOrderAmount = SUM(Quantity * UnitPrice)
 From Customers
   join Orders
     on Orders.CustomerID = Customers.CustomerID
   join OrderDetails
   on Orders.OrderID = OrderDetails.OrderID
 Where
   OrderDate >= '20160101'
   and OrderDate < '20170101'
 Group By
   Customers.CustomerID
   ,Customers.CompanyName
)
,CustomerGrouping as (
 Select
   CustomerID
   ,CompanyName
   ,TotalOrderAmount
   ,CustomerGroup =
     case
       when TotalOrderAmount >= 0 and TotalOrderAmount < 1000 then 'Low'
       when TotalOrderAmount >= 1000 and TotalOrderAmount < 5000 then 'Medium'
       when TotalOrderAmount >= 5000 and TotalOrderAmount <10000 then 'High'
       when TotalOrderAmount >= 10000 then 'Very High'
    end
 from Orders2016
 -- Order by CustomerID
)
Select
 CustomerGroup
 , TotalInGroup = Count(*)
 , PercentageInGroup = Count(*) * 1.0/ (select count(*) from CustomerGrouping)
from CustomerGrouping
group by CustomerGroup
order by TotalInGroup desc

讨论

在答案中,我们添加了一个名为CustomerGrouping的中间CTE。CustomerGrouping被引用两次—— 一次是获取组中的客户总数,另一次是获得客户总数,作为百分比的分母。

请注意,在第二个CTE中的Order by CustomerID已经被注释掉了。如果你把它放在里面,你会得到错误。

51.灵活的客户分组

答案

;with Orders2016 as (
 Select
   Customers.CustomerID
   ,Customers.CompanyName
   ,TotalOrderAmount = SUM(Quantity * UnitPrice)
 From Customers
   Join Orders
     on Orders.CustomerID = Customers.CustomerID
   Join OrderDetails
     on Orders.OrderID = OrderDetails.OrderID
 Where
   OrderDate >= '20160101'
   and OrderDate < '20170101'
 Group by
   Customers.CustomerID
   ,Customers.CompanyName
)
Select
 CustomerID
 ,CompanyName
 ,TotalOrderAmount
 ,CustomerGroupName
from Orders2016
 Join CustomerGroupThresholds
   on Orders2016.TotalOrderAmount between
      CustomerGroupThresholds.RangeBottom and CustomerGroupThresholds.RangeTop
Order by CustomerID

讨论

请注意,这给出的结果与原来的问题相同。但是,不要使用Case语句中的硬编码值来定义CustomerGroups的边界,而是将它们放在表中。

这样做的好处是,你不需要在对客户进行分组的每个查询中重复以下代码,因为它是在表中定义的。

,CustomerGroup =
   case
     when TotalOrderAmount >= 0 and TotalOrderAmount < 1000 then 'Low'
     when TotalOrderAmount >= 1000 and TotalOrderAmount < 5000 then 'Medium'
     when TotalOrderAmount >= 5000 and TotalOrderAmount <10000 then 'High'
     when TotalOrderAmount >= 10000 then 'Very High'
   end

另外,请看看CustomerGroupThresholds中的值。

select * From CustomerGroupThresholds

请注意,关于范围底部和范围顶部,这些行之间没有重叠。如果是Money之外的数据类型(小数点后4位),可能会有间隙或重叠。


未完待续

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


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

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

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

相关文章

qmt量化交易策略小白学习笔记第29期【qmt编程之获取行业概念数据--如何下载板块分类信息及历史板块分类信息】

qmt编程之获取行业概念数据 qmt更加详细的教程方法&#xff0c;会持续慢慢梳理。 也可找寻博主的历史文章&#xff0c;搜索关键词查看解决方案 &#xff01; 感谢关注&#xff0c;咨询免费开通量化回测与获取实盘权限&#xff0c;欢迎和博主联系&#xff01; 获取行业概念数…

在typora中利用正则表达式,批量处理图片

一&#xff0c;png格式 在 Typora 中批量将 HTML 图片标签转换为简化的 Markdown 图片链接&#xff0c;且忽略 alt 和 style 属性&#xff0c;可以按照以下步骤操作&#xff1a; 打开 Typora 并加载你的文档。按下 Ctrl H&#xff08;在 Windows/Linux 上&#xff09;或 Cmd…

【NOI-题解】1389 - 数据分析1750 - 有0的数1457 - 子数整除1121 - “倒”数1962. 数值计算

文章目录 一、前言二、问题问题&#xff1a;1389 - 数据分析问题&#xff1a;1750 - 有0的数问题&#xff1a;1457 - 子数整除问题&#xff1a;1121 - “倒”数问题&#xff1a;1962. 数值计算 三、感谢 一、前言 本章节主要对循环中带余除法部分题目进行讲解&#xff0c;包括…

CV预测:快速使用LeNet-5卷积神经网络

AI预测相关目录 AI预测流程&#xff0c;包括ETL、算法策略、算法模型、模型评估、可视化等相关内容 最好有基础的python算法预测经验 EEMD策略及踩坑VMD-CNN-LSTM时序预测对双向LSTM等模型添加自注意力机制K折叠交叉验证optuna超参数优化框架多任务学习-模型融合策略Transform…

2024年先进算法与人机交互国际会议(ICCHSE 2024)

2024 International Conference on Advanced Algorithms and Human Computer Interaction 【1】大会信息 会议简称&#xff1a;ICAAHIE 2024 大会时间&#xff1a;2024-07-19 大会地点&#xff1a;中国桂林 截稿时间&#xff1a;2024-07-05(以官网为准&#xff09; 审稿通知&a…

Ajax的应用

1. Ajax Ajax是Asynchronous Javascript And XML&#xff08;异步JavaScript和XML&#xff09;的缩写。 Ajax技术描述了使用脚本操纵HTTP和Web服务器进行数据交换&#xff0c;在页面不刷新的情况下&#xff0c;实现页面的局部更新。 重点&#xff1a; Ajax 是一种在无需重新加…

服务器再升级!64线程服务器震撼上线,全新渲染体验等你来解锁

秉承着 “科技赋能创意&#xff0c;连接创造价值”的使命&#xff0c; 经过精心的策划和筹备&#xff0c; 蓝海创意云 64线程服务器&#xff0c; 以全新的面貌&#xff0c;优惠的价格&#xff0c; 与大家见面了&#xff01; 诚邀您一起&#xff0c;解锁全新的渲染体验&am…

如何利用AI绘图,生成同一人物(最好为二次元)的不同动作和不同表情的图片?

Ai绘画有一个很现实的问题&#xff0c;要保证每次画出的都是同一个人物的话&#xff0c;很费劲。 Midjourney就不必说了&#xff0c;人物的高度一致性一直得不到很好的解决。而在Stable Diffusion&#xff08;SD&#xff09;中&#xff0c;常用办法是通过同一个Seed值&#xf…

Android低代码开发 - InputMenuPanelItem详解

我们知道MenuPanel是一个菜单面板容器&#xff0c;它里面可以放各式各样的菜单和菜单组。今天我们就来详细讲解输入菜单这个东西。 InputMenuPanelItem源码 package dora.widget.panel.menuimport android.content.Context import android.text.Editable import android.text…

KEYSIGHT N1000A 采样示波器 支持哪些类型的示波器模块?

N1000A Keysight 高性能宽带宽示波器&#xff0c;它支持多种类型的模块&#xff0c;这些模块可以根据用户的需求进行选择和配置&#xff0c;以执行精密的光学、电气和TDR/TDT/S参数分析。以下是一些支持的模块类型&#xff1a; 光通信模块&#xff1a;这些模块支持深入的收发信…

量化、剪枝、蒸馏,这些大模型黑话到底说了些啥?

扎克伯格说&#xff0c;Llama3-8B还是太大了&#xff0c;不适合放到手机中&#xff0c;有什么办法&#xff1f; 量化、剪枝、蒸馏&#xff0c;如果你经常关注大语言模型&#xff0c;一定会看到这几个词&#xff0c;单看这几个字&#xff0c;我们很难理解它们都干了些什么&…

【图书推荐】《Spark入门与大数据分析实战》

本书重点 广告点击实时大数据分析、电影影评大数据分析&#xff0c;这两个综合项目适合作为课题论文、毕业论文素材&#xff0c;值得收藏。 内容简介 本书基于Spark 3.3.1框架展开&#xff0c;系统介绍Spark生态系统各组件的操作&#xff0c;以及相应的大数据分析方法。 本…

亿达四方:一站式SolidWorks代理服务,打造设计竞争力

在当今瞬息万变的设计与制造领域&#xff0c;高效、精准的3D设计软件已成为推动企业创新与发展的核心驱动力。作为业界知名的SolidWorks一站式代理服务商&#xff0c;亿达四方致力于为企业搭建从软件采购到技术应用的全方位桥梁&#xff0c;全面赋能设计团队&#xff0c;助力企…

如何保障生物制药企业,HPC环境下数据下载的安全性问题?

许多不同类型的公司和组织可能会使用高性能计算&#xff08;HPC&#xff09;来解决各种复杂的问题。制药和生物技术企业使用高性能计算&#xff08;HPC&#xff09;的方式多种多样&#xff0c;同时也涉及HPC环境下数据下载安全性问题的考量。主要包括以下几个方面&#xff1a; …

把裤袜换成黑丝(Stable Diffusion进阶篇: ComfyUI 局部重绘)

先让大伙打起精神来 局部重绘 局部重绘适用于那些对整个画面还比较满意&#xff0c;只是想修改部分区域的情况。 在WebUI中通常选择用涂抹重绘区域的方式来让AI知道要重绘哪里&#xff0c;这个被涂抹的区域会被AI识别为黑白区域&#xff0c;白色的部分也就是所谓的重绘蒙版“…

kali中安装zsteg教程

1、下载文件 git clone http://www.github.com/zed-0xff/zsteg 2、第一步需要保证虚拟机是有网络的&#xff0c;不然无法克隆 3、可以将网络设置成如下后重启&#xff0c;访问百度看看能不能访问&#xff0c;若可以访问&#xff0c;则进行下一步 4、查看源&#xff0c;删除源&…

WinForm之TCP服务端

目录 一 原型 二 源码 一 原型 二 源码 using System.Net; using System.Net.Sockets; using System.Text;namespace TCP网络服务端通讯 {public partial class Form1 : Form{public Form1(){InitializeComponent();}TcpListener listener null;TcpClient handler null;Ne…

未实施数据加密的企业,如何快速符合等保2.0标准?

企业若未实施数据加密&#xff0c;想要快速符合等保2.0标准&#xff0c;可以遵循以下步骤&#xff1a; 风险评估与规划&#xff1a; • 首先&#xff0c;进行全面的信息安全风险评估&#xff0c;识别数据处理的关键环节、敏感信息类型及其存储、传输路径。 • 基于评估结果&…

【SpringBoot + Vue 尚庭公寓实战】公寓杂费接口实现(八)

【SpringBoot Vue 尚庭公寓实战】公寓杂费接口实现&#xff08;八&#xff09; 文章目录 【SpringBoot Vue 尚庭公寓实战】公寓杂费接口实现&#xff08;八&#xff09;1、公寓杂费业务介绍2、公寓杂费逻辑模型介绍3、接口实现3.1、保存或更新杂费值3.2、保存或更新杂费名称3…

使用‘消除’技术绕过LLM的安全机制,不用训练就可以创建自己的nsfw模型

开源的大模型在理解和遵循指令方面都表现十分出色。但是这些模型都有审查的机制&#xff0c;在获得被认为是有害的输入的时候会拒绝执行指令&#xff0c;例如会返回“As an AI assistant, I cannot help you.”。这个安全功能对于防止误用至关重要&#xff0c;但它限制了模型的…