博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
提升查询技能,这7条SQL查询错误必须解决
阅读量:2108 次
发布时间:2019-04-29

本文共 3217 字,大约阅读时间需要 10 分钟。

全文共3183字,预计学习时长8分钟

 

图源:unsplash

本文将指出一些常见但却总是被忽略的错误,请静下心来,准备好提升查询技能吧!

 

让我们以一个虚构的业务为例。假设你是亚马逊电子商务分析团队的一员,需要运行几个简单的查询。你手头有两个表,分别为“product(产品)”和“discount (折扣)”。

 

1.计算NULL字段的数目

 

为了计算null字段的数目,要掌握COUNT函数的工作原理。假设计算产品数量时,要求计入表格“product”的“product id”主键列中遗漏的字段。

 

SELECT COUNT(product_id)FROM product;Result: 3

 

由于要求计入“product id”列中的null值,查询结果应该为4,但COUNT()函数不会将null值计数。

 

解决方法:使用COUNT(*)函数。该函数可以将null值计数。

 

Select Count(*)From product;Result: 4

 

这个操作很简单,但是在编写复杂的查询时总会被忽略。

 

2.使用保留字作为列名

 

SELECT product_id,RANK() OVER (ORDER BY price desc) As RankFROM product;

 

由于列名“Rank”是Rank函数的保留字,该查询结果出错。

 

解决方法:

 

SELECT product_id,RANK() OVER (ORDER BY price desc) As ‘Rank’FROM product;

 

加上单引号,即可得到想要的结果。

 

3.NULL的比较运算

 

SELECT product_nameFROM productWHERE product_id=NULL;

 

由于使用了比较运算符“=”,此处运算会出现异常,使用另一比较运算符“!=”运算也会出现异常。这里的逻辑问题在于,你编写的查询得出的是“product id”列的值是否未知,而无法得出这一列的值是否是未知的产品。

 

解决方法:

 

SELECT product_nameFROM productWHERE product_id ISNULL;

 

4.ON子句过滤和WHERE子句过滤的区别

 

这是一个非常有趣的概念,会提高你对于ON子句过滤和WHERE子句过滤之间区别的基本理解。这并不完全是一个错误,只是演示了两者的用法,你可以根据业务需求选择最佳方案。

图源:unsplash

SELECT d.product_id,price,discountFROM product p RIGHT JOIN discount d ONp.product_id=d.product_idWHERE p.product_id>1;

 

结果:

 

在这种情况下,过滤条件在两个表格连接之后生效。因此,所得结果不包含d.product_id≤1的行(同理,显然也不包含p.product≤1的行)。

 

解决方法:使用AND,注意结果上的不同。

 

SELECT d.product_id,price,discountFROM product p RIGHT JOIN discount d ONp.product_id=d.product_idAND p.product_id>1;

 

结果:

 

在这里,条件语句AND在两个表格连接发生之前计算。可以把此查询看作只适用于一个表(“product”表)的WHERE子句。现在,由于右连接,结果中出现了d.product_id≤1的行(显然还有p.product_id>1的行)。

 

请注意,ON子句过滤和WHERE子句过滤只在左/右/外连接时不同,而在内连接时相同。

 

5.在同一查询的WHERE子句中使用Windows函数生成的列&使用CASE WHEN子句

 

注意,不要在同一查询的WHERE子句中使用通过Windows函数生成的列名以及CASE WHEN子句。

 

SELECT product_id,RANK() OVER (ORDER BY price desc) AS rkFROM productWHERE rk=2;

 

因为列rk由Windows函数生成,并且在同一查询的WHERE子句中使用了该列,这个查询结果会出现异常。

 

解决方法:这一问题可以通过使用临时表或者子查询解决。

 

WITH CTE AS(SELECT product_id,RANK() OVER (ORDER BY price desc) AS rkFROM product)SELECT product_idFROMCTEWHERE rk=2;

 

 

SELECT product_idFROM(SELECT product_id,RANK() OVER (ORDER BY price desc) AS rkFROM product;)WHERE rk=2;

 

同样的方法也适用于使用CASE WHEN子句创建的列。请记住,Windows函数只能出现在SELECT或ORDER BY子句中。

 

6.BETWEEN的使用不正确

 

如果不清楚BETWEEN的有效范围,也许会得不到想要的查询结果。BETWEEN x AND y语句的有效范围包含x和y。

 

SELECT *FROM discountWHERE offer_valid_till BETWEEN ‘2019/01/01’ AND ‘2020/01/01’ORDER BY offer_valid_till;

 

结果:

 

在查询中,也许我们只想得到2019年的所有日期,但是结果中还包含了2020年1月1日。这是因为BETWEEN语句的有效范围包含2019/01/01和2020/01/01。

 

解决方法:相应地调整范围可以解决这个问题。

 

SELECT *FROM discountWHERE offer_valid_till BETWEEN ‘2019/01/01’ AND ‘2019/12/31’ORDER BY offer_valid_till;

 

结果:

 

现在,所有查询结果均为2019年的日期。

 

7.在GROUP BY语句后使用WHERE子句

 

在编写GROUP BY语句时,请注意WHERE子句的位置。

 

SELECT category,AVG (price)FROM product p INNER JOIN discount d ONp.product_id=d.product_idGROUP BY categoryWHERE discount_amount>10;

 

由于将WHERE子句放在GROUP BY语句后,此查询是错误的。这是为什么呢?

 

WHERE子句用于过滤查询结果,这一步要在将查询结果分组之前实现,而不是先分组再过滤。正确的做法是先应用WHERE条件过滤减少数据,再使用GROUP BY子句通过聚合函数将数据分组(此处使用聚合函数AVG)。

 

解决方法:

 

SELECT category,AVG (price)FROM product p INNER JOIN discount d ONp.product_id=d.product_idWHERE discount_amount>10GROUP BY category;

 

请注意主要SQL语句的执行顺序:

 

· FROM 子句

· WHERE 子句

· GROUP BY 子句

· HAVING 子句

· SELECT 子句

· ORDER BY 子句

图源:Pexels

以上包含了大部分让人不解的错误,尤其是对初学者而言。正如亨利·福特所说:“唯一的错误是我们从中学不到任何东西”,希望这篇文章能帮助你精进查询技能。

一起分享AI学习与发展的干货

欢迎关注全平台AI垂类自媒体 “读芯术”

(添加小编微信:dxsxbb,加入读者圈,一起讨论最新鲜的人工智能科技哦~)

转载地址:http://gqyef.baihongyu.com/

你可能感兴趣的文章
Chrome调试工具奇淫技
查看>>
30分钟快速掌握Bootstrap
查看>>
如何针对业务做DB优化
查看>>
程序猿都该知道的MySQL秘籍
查看>>
Eclipse全面提速小技巧
查看>>
前端程序员必知的30个Chrome扩展
查看>>
memcached分布式实现原理
查看>>
怎么成为架构师
查看>>
40个重要的HTML 5面试问题及答案
查看>>
在Java中如何高效判断数组中是否包含某个元素
查看>>
设计模式总结
查看>>
什么时候可以使用Ehcache缓存
查看>>
Java核心知识点-JVM结构和工作方式
查看>>
Java编程中“为了性能”一些尽量做到的地方
查看>>
Java并发编程:线程池的使用
查看>>
redis单机及其集群的搭建
查看>>
Java多线程学习
查看>>
检查Linux服务器性能
查看>>
Java 8新的时间日期库
查看>>
Chrome开发者工具
查看>>