mysql vs mysqliSQL语言有许多方法来过滤记录集。“您的SELECT语句”中的“其中”子句是大多数人列出过滤掉记录的业务规则的位置。您可以使用SQL中的“加入”语句,但通常更难以阅读。“不存在”语句使用子查询来过滤介绍底层子查询中不存在的记录。此逻辑有时很难掌握新的SQL编码器,但本文介绍了不存在语句的逻辑和替代方案。

通过Udemy.com的课程了解SQL入门。

子查询和SQL语句

子查询基本上是查询中的查询。下面的查询是一个标准的、简单的SQL选择语句:

select * from customer where customerId = 5

“select *”部分告诉SQL数据库返回所有列。SQL中的星号表示要返回所有列,但也可以单独指定列。事实上,大多数数据库设计人员希望您指定列,因为星号返回您不需要的审计信息,如创建日期、更新日期和外键信息。

“where”子句表示您只想返回id为5的客户。当然,您可以返回多条记录。您可以从上面的语句中假设“customerId”是惟一的列。customerId对于每个客户应该只有一个值,因此可以假设上面的查询只返回一条记录。然而,它也取决于数据库设计。好的数据库设计应该具有标识特定列中包含的信息类型的列名。

您可以添加子查询,而不是使用" where customerId = 5 "子句。这就是NOT EXISTS工作的地方。例如,以以下查询为例:

从不存在的客户中选择*(从订单中选择CustomerID)

上面的语句基本上是说“给我订单表中customerId不存在的所有客户记录”。因此,业务逻辑是“我想查看所有没有订单的客户”。NOT EXISTS语句与EXISTS语句相反,因此如果希望看到相反的结果,只需反转业务逻辑即可。例如,下面的语句给出了相反的结果:

select * from customers where EXISTS (select customerId from orders)

上面的声明说:“给我客户下订单的所有客户记录。”根据业务逻辑,您可能需要在应用程序的不同部分使用EXISTS和NOT EXISTS。

当您运行诸如上面的查询时,应该指出的是,子查询首先运行。存在的子查询且不存在语句是返回订单记录的查询。此查询首先运行。然后,主要或“外部”查询运行。在上面的示例中,外部查询是基于客户表的SELECT语句。考虑以下查询:

select * from customers where NOT EXISTS (select customerId from orders where createdate >= getdate() - 30)

在本声明中,根据订单日期返回订单列表。假设“创建”是包含订单创建日期的列。因此,从后30天内放置的任何订单都从子查询返回。然后将这些记录用于外部查询,这再次是SELECT语句对客户表运行。

SQL语言新手?在Udemy.com上学习如何为数据库编程。

将NOT EXISTS与其他Where子句过滤器组合在一起

where子句可以接受多个逻辑过滤器。假设您想要获得下过订单的客户列表,但您只想要在最近60天内注册的客户。例如,您可能想知道有多少客户下了订单,但您想要的是“新”客户。“New”是一个任意值,因此您将该值设置为60天。您可以编写匹配此业务逻辑的SQL语句。通常可以通过多种方式编写SQL语句来匹配业务逻辑,但在本例中,您希望使用NOT EXISTS语句。以下代码是为指定的业务逻辑编写代码的SQL语句:

select * from customers where EXISTS (select customerId from orders where createdate >= getdate() - 30) and NOT EXISTS (select customerId from customers where createdate <= getdate() - 60))

上面的语句结合了EXISTS和NOT EXISTS语句。首先,运行EXISTS子查询。这是一个子查询,用于获取最近30天内下过订单的客户列表。接下来,运行NOT EXISTS子查询。这个子查询获取60天以前创建的客户列表。由于第二个子查询使用NOT EXISTS语句,主查询将与针对客户数据库的NOT EXISTS子查询进行匹配,并过滤掉子查询中存在的记录。因此,它只获取不在not EXISTS子查询中的customerId的记录。

而EXISTS语句则相反。where子句的这一部分保存了存在于相应EXISTS子查询中的记录。

您可以使SQL语句变得简单得多。上面的陈述可以用不同的方法来表示,这些方法可能要简单得多。使用EXISTS或NOT EXISTS语句重写SQL语句的典型方法是使用连接语句。下面的代码是重写上述语句的示例:

从Customers C加入ON CORE ON C加入ON C.CustomerID = O.CustomerID的位置O.CustomerID,其中O.Createdate> = GetDate() -  30和C.Createdate <= GetDate() -  60

此语句包含与前一个业务逻辑相同的业务逻辑。差异是加入声明。对于大多数数据库设计,您的数据库管理员或DBA将要求您在适当的情况下使用连接而不是子查询。使用JOIN,两个表客户和订单在主键和外键上连接在一起。假设客户表“CustomerID”列是客户表的主键,并且订单表中的CustomerID是外键。您可以通过查询假设CustomerID是唯一的,并且主要索引是群集索引。然后,您假设Orders表中的外键被设置为索引。这种设计将保持您的表格的性能效率。

您可能希望了解子查询和加入之间的区别。您必须解释的一个主要区别是无效。某些数据库设计人员允许NULLS,但即使它们没有,即使没有链接表将受到影响。在JOIN语句中,如果不存在相应的顺序,则会完全过滤记录。

例如,假设您有一个有订单的客户和一个没有订单的客户。使用连接语句,您将无法获得记录集中没有订单的客户。原因是join语句没有相应的链接顺序,因此会过滤掉客户。对于exist语句,null仍然算数。例如,如果数据库没有正确设置,那么orders customerId列中可能会有一些空值。当子查询的where子句基于订单创建日期时,这些记录仍然会返回。如果客户表中有一个空值,订单表中有一个空值,那么空值就会匹配。

获取这些空值的可选方式是左连接。左连接返回所有客户记录,然后返回任何链接的订单记录。如果相应的订单记录中没有记录,则此表的列将返回NULL。

连接和子查询的概念很难掌握,因此测试它们的最佳方法是在SQL工具中编写它们,并在数据库中运行它们。下面的代码使用左连接代替表的连接:

选择*来自客户C左连接ON C.CustomerID = O.CustomerID,其中O.Createdate> = GetDate() -  30和C.createdate <= GetDate() -  60

从技术上讲,您应该得到相同的数据集,但是左连接可以帮助您找到孤立记录,即订单表中存在的没有连接客户Id的记录。这是糟糕的表设计,SQL数据库引擎应该阻止删除客户而不删除客户订单。由于这个原因,大多数数据库管理员避免允许对任何表执行删除查询。相反,你有一个“活跃”和“不活跃”栏。将列设置为非活动的,设置其审计日期,然后创建新记录。此记录将成为活动记录,存储过程应考虑这些活动和非活动记录。

“在”和“不在”语句

EXISTS和NOT EXISTS是SQL过程中使用的两个较好的语句。但是,您也可以使用IN和NOT IN。这两个语句还使用子查询过滤记录。下面的代码使用上述EXISTS和NOT EXISTS语句,将它们切换为IN和NOT IN语句:

select customerId from orders where createdate >= getdate() - 30 and NOT IN (select customerId from customers where createdate <= getdate() - 60))

上面的语句与上一个语句相同的业务逻辑,并返回应用程序的相同记录集。

不存在的执行计划是不同的。但是,您希望选择最快的计划,但仍然符合您的业务逻辑。SQL Server Management Studio有一个执行计划,告诉您哪一个最有效,遵循业务逻辑。

性能和速度是决定执行计划和如何设计查询的重要因素。您希望查询准确地按照业务逻辑指定的方式获取和编辑数据,但又不希望使用花费太长时间的功能。例如,您希望将where子句集中在包含索引的列上。

索引有助于订购数据库表。这些数据库对象大大提高了性能。例如,假设您对包含CustomerID的客户列进行多次查询。您要创建对此列运行的查询,因为它不仅是主键和唯一,而且还使用索引。主键会自动设置为索引,因此在设置主键时无需手动创建索引。但是,您需要手动在表上设置其他索引。

例如,假设您的客户表包含注册日期列,并且在许多查询中使用此列。您可以在此列上设置索引以加快查询。您还希望加入这些列。加入应该使用索引列,因为这些速度也加快了查询。

使用索引和执行计划,可以保持查询的流线型,避免降低数据库的速度。如果有几个对数据库表运行的查询,可能需要几秒钟才能返回一个记录集。这看起来可能不是很多时间,但是当你创建像电子商务商店这样的网站时,几秒钟是很重要的。当加载一个网页的时间过长时,用户更有可能跳出来。出于这个原因,搜索引擎(如谷歌)也使用速度作为页面排名的指标。

确定最佳陈述的最简单方法是写下您的业务逻辑。是否存在有意义?不存在有意义吗?在将其上传到生产数据库之前,请确保彻底测试查询。检查您的索引和任何数据完整性问题的表。数据库管理员将帮助您,但是当您无法正确设计表时,会发生不可预见的问题。

Udemy.com可以帮助您进行表设计和理解SQL语言。SQL语言在不同平台上是相似的,但在SQL Server、MySQL和Oracle之间有细微的差别。参加Udemy.com的初级SQL课程来熟悉这门语言。

SQL顶级课程

SQL&PostgreSQL为初学者:成为一个SQL专家
Jon Avis - SQL讲师
4.6 (3,338)
畅销书
SQL和PostgreSQL:完整的开发者指南
Stephen主梁
4.7 (1,611)
评价最高
用于技术和数据科学面试的SQL
《365职业》,Tina Huang报道
4.7 (46)
热&新
完整SQL训练营2021:从零到英雄
何塞波罗拉
4.7 (101305)
畅销书
Ultimate MySQL BootCamp:从SQL初学者到专家
柯尔特·斯蒂尔,伊恩·斯库诺弗
4.6 (55416)
畅销书
用于数据分析和商业智能的SQL - MySQL
365年职业生涯
4.6 (28657)
畅销书
精通SQL For数据科学
Imtiaz艾哈迈德
4.6 (7746)
高级SQL: SQL专家认证准备课程
•代码之星学院,全球90,000多名学生
4.4 (2390)
完成SQL和数据库训练营:零到精通[2021]
安德烈Neageie,Mo Binni
4.6 (1597)
SQL初学者:使用MySQL学习SQL和数据库设计
Tim Buchalka的学习编程学院,Jon Avis - SQL讲师
4.5 (12632)
从头开始学习SQL +安全(笔)测试
拉胡尔·赫尔蒂
4.5 (1650)
畅销书
SQL For数据科学与谷歌大查询
克里斯征税
4.5 (1303)

多个SQL课程

SQL学生还学习

赋予你的团队。引领行业。

通过Udemy for Business订阅您组织的在线课程和数字学习工具图书馆。

请求演示