要提高查询技能,必须解决这7个SQL查询错误准备好提高您的查询技能吧!让我们以一个虚构的企业为例。假设您是亚马逊电子商务分析团队的一员,需要运行一些简单的查询。你手头有两个表,分别是“产品(product)”和“折扣(discount)”。1、计算NULL字段的个数要想计算出NULL字段的个数,必须掌握COUNT函数的工作原理。假设在计算产品数量时,需要将“product”表的“productid”主键列中缺失的字段包含在内。SELECTCOUNT(product_id)FROMproduct;结果:3由于需要统计“productid”列的空值,所以查询结果应该是4,但是COUNT()函数不会统计空值。解决方案:使用COUNT(*)函数。此函数可以计算空值。SelectCount(*)Fromproduct;Result:4这个操作很简单,但是写复杂查询的时候总会被忽略。2.使用保留字作为列名SELECTproduct_id,RANK()OVER(ORDERBYpricedesc)AsRankFROMproduct;由于列名“Rank”是Rank函数的保留字,所以查询结果是错误的。解决方案:SELECTproduct_id,RANK()OVER(ORDERBYpricedesc)As'Rank'FROMproduct;添加单引号以获得所需的结果。3、NULL比较操作SELECTproduct_nameFROMproductWHEREproduct_id=NULL;由于使用了比较运算符“=”,这个操作会出现异常,使用另一个比较运算符“!=”也会出现异常。这里的逻辑问题是你写的查询是为了判断“productid”列的值是否未知,而不是这个列的值是否是未知产品。解决方案:SELECTproduct_nameFROMproductWHEREproduct_idISNULL;4.ON子句过滤和WHERE子句过滤的区别这是一个很有趣的概念,将提高你对ON子句过滤和WHERE子句过滤的区别的基本理解。这不完全是一个错误,它只是演示了两者的用法,您可以根据您的业务需求选择最佳的一个。SELECTd.product_id,price,discountFROMproductpRIGHTJOINdiscountdONp.product_id=d.product_idWHEREp.product_id>1;结果:本例中,过滤条件在两表join后生效。因此得到的结果中不包含d.product_id≤1的行(同理,显然也不包含p.product≤1的行)。解决方案:使用AND,注意结果的差异。SELECTd.product_id,price,discountFROMproductpRIGHTJOINdiscountdONp.product_id=d.product_idANDp.??product_id>1;结果:这里,条件语句AND在两个表的连接发生之前被评估。将此查询视为仅适用于一个表(“产品”表)的WHERE子句。现在,由于右连接,d.product_id≤1的行出现在结果中(显然还有p.product_id>1的行)。注意ON子句过滤和WHERE子句过滤只是左/右/外连接不同,内连接相同。5.在同一查询的WHERE子句中使用Windows函数生成的列名&使用CASEWHEN子句注意不要在同一查询的WHERE子句中使用Windows函数生成的列名和CASEWHEN子句.SELECTproduct_id,RANK()OVER(ORDERBYpricedesc)ASrkFROMproductWHERErk=2;因为rk列是Windows函数生成的,并且在同一个查询的WHERE子句中使用,所以这个查询的结果会出现异常。解决方案:这个问题可以通过使用临时表或者子查询来解决。WithCTEAS(SELECTproduct_id,RANK()OVER(ORDERBYpricedesc)ASrkFROMproduct)SELECTproduct_idFROMCTEWHERErk=2;或SELECTproduct_idFROM(SELECTproduct_id,RANK()OVER(ORDERBYpricedesc)ASrkFROMproduct;)WHERErk=2;同样的方法也适用于使用CASEWHERErk=2;子句创建的列。.请记住,Windows函数只能出现在SELECT或ORDERBY子句中。6.BETWEEN的使用不正确。如果不知道BETWEEN的有效范围,可能得不到想要的查询结果。BETWEENxANDy语句的有效范围包括x和y。SELECT*FROMdiscountWHEREoffer_valid_tillBETWEEN'2019/01/01'AND'2020/01/01'ORDERBYoffer_valid_till;结果:在查询中,可能我们只想获取2019年的所有日期,但是结果中还包括2020年1月1日。这是因为BETWEEN语句的有效范围包括2019/01/01和2020/01/01.解决方法:相应地调整范围可解决此问题。SELECT*FROMdiscountWHEREoffer_valid_tillBETWEEN'2019/01/01'AND'2019/12/31'ORDERBYoffer_valid_till;结果:现在查询的结果都是2019年的日期。7.在GROUPBY语句后使用WHERE子句编写GROUPBY语句时,请注意WHERE子句的位置。SELECTcategory,AVG(price)FROMproductpINNERJOINdiscountdONp.product_id=d.product_idGROUPBYcategoryWHEREdiscount_amount>10;由于WHERE子句放在GROUPBY语句之后,所以这个查询是错误的。为什么是这样?WHERE子句用于过滤查询结果。这一步应该在对查询结果进行分组之前实现,而不是先分组再过滤。正确的做法是先应用WHERE条件对数据进行过滤归约,然后使用GROUPBY子句通过聚合函数(这里使用聚合函数AVG)对数据进行分组。解决方案:SELECTcategory,AVG(price)FROMproductpINNERJOINdiscountdONp.product_id=d.product_idWHEREdiscount_amount>10GROUPBYcategory;请注意主要SQL语句的执行顺序:FROM子句WHERE子句GROUPBY子句HAVING子句SELECT子句ORDERBY子句上面包含了大部分容易混淆的错误,特别适合初学者。正如亨利·福特所说:“唯一的错误是我们没有从中学到任何东西”,希望本文能帮助您提高查询技巧。
