来源:sunsplash

SQL被广泛运用于数据剖析和数据提取。
易上手,受到业内人士的同等好评

只管刚开始编写SQL相称随意马虎,但是出错率也是相称的高。

phpsql错误避免5个编写SQL查询时常涌现的毛病 NoSQL

下面是小芯整理的,在编写SQL查询代码时大家常常犯的5个缺点。

示例很短,可能看起来很大略。
但是,在处理更大的查询时,这些缺点可就不会一览无余了。
个中一些示例是特定于AWS Redshift的,而另一些则会涌如今其他SQL数据库(Postgres、MySQL等)。
这些示例该当在本地数据库上运行,或者可以利用SQLFiddle在线运行。

示例SQL查询可下载。

来源:Pexels

设定

创建两个临时表,个中有几个条款有助于处理示例。

Sales表

该表包含带有韶光戳、产品、价格等的发卖条款。
请把稳,key列是唯一的,其他列中的值可以重复(例如ts列)。

DROP TABLE IF EXISTSsales;

CREATE TEMPORARY TABLE sales

(

key varchar(6),

ts timestamp,

product integer,

completed boolean,

price float

);INSERT INTO sales

VALUES ('sale_1', '2019-11-08 00:00', 0, TRUE, 1.1),

('sale_2', '2019-11-08 01:00', 0, FALSE,1.2),

('sale_3', '2019-11-08 01:00', 0, TRUE,1.3),

('sale_4', '2019-11-08 01:00', 1, FALSE,1.4),

('sale_5', '2019-11-08 02:00', 1, TRUE,1.5),

('sale_6', '2019-11-08 02:00', 1, TRUE,1.5);SELECT FROM sales;

Hourly delay表

该表包含某一天每小时的延迟韶光。
请把稳,ts列不才表中是唯一的。

DROP TABLE IF EXISTShourly_delay;

CREATE TEMPORARY TABLE hourly_delay

(

ts timestamp,

delay float

);

INSERT INTO hourly_delay

VALUES ('2019-11-08 00:00', 80.1),

('2019-11-08 01:00', 100.2),

('2019-11-08 02:00', 70.3);SELECT FROM hourly_delay;

1.按相同韶光戳排序

检索每种产品最近一次的售价:

SELECT price

FROM (SELECT price, row_number() OVER (PARTITION BYproduct ORDER BY ts DESC) AS ix FROM sales) ASq1

WHERE ix = 1;

以上查询的问题是多个发卖具有相同的韶光戳。
此查询在相同数据上的连续运行可能得出不同的结果。
下图可见,产品0在2019-11-11-08 01:00有两次发卖,价格分别为1.2和1.3。

用下一个缺点修复这个查询:)

2. 根据条件打算均匀值

打算完成发卖的产品的均匀价格。
值是(1.1 + 1.3 + 1.5 + 1.5)/ 4,即1.35。

SELECT avg(price)

FROM (SELECT CASE WHEN completed = TRUETHEN price else 0 END AS price FROM sales) ASq1;

当运行查询时,值为0.9。
为什么?由于发生了这一打算:(1.1+0+1.3+0+1.5+1.5)/6是0.9。
查询中的缺点是,将0设置为不应包含的项。
应利用NULL而不是0。

SELECT avg(price)

FROM (SELECT CASE WHEN completed = TRUETHEN price else NULL END AS price FROMsales) AS q1;

当前,输出和估量一样是1.35。

3.打算整数列的均匀值

打算含有整数的product列的均匀值。

SELECT avg(product)

FROM sales;

Product列中有3个0和3个1,预估均匀值为0.5。
大多数数据库(例如最新版本的Postgres)将返回0.5,但是Redshift将返回0,由于它不会自动将product列逼迫转换为float。
因此须要将其逼迫转换为float类型:

SELECT avg(product::FLOAT)

FROM sales;

4. 内连接

假设要对每天的所有发卖延迟进行汇总,并打算每天的均匀发卖价格。

SELECT t2.ts::DATE, sum(t2.delay),avg(t1.price)

FROM hourly_delay AS t2

INNER JOIN sales ASt1 ON t1.ts = t2.ts

GROUP BY t2.ts::DATE;

结果是缺点的!
以上查询将hourly_delay表中的delay列乘以倍数,如下图所示。
这是由于按韶光戳连接,该韶光戳在hourly_delay表中是唯一的,但在sales表中会重复。

为了修复这个问题,要在一个单独的子查询中为每个表打算统计信息,然后连接汇总。
这使得韶光戳在两个表中都是唯一的。

SELECT t1.ts, daily_delay, avg_price

FROM (SELECT t2.ts::DATE, sum(t2.delay) ASdaily_delay FROM hourly_delay AS t2 GROUP BYt2.ts::DATE) AS t2

INNER JOIN (SELECTts::DATE AS ts, avg(price) AS avg_price FROM sales GROUPBY ts::DATE) AS t1 ON t1.ts = t2.ts;

5.将列添加到ORDER BY

对上述缺点的补救是显而易见的。
将key列添加到ORDER BY,这样一来,查询结果就可以在相同数据上重复涌现——快速修复。

SELECT price

FROM (SELECT price, row_number() OVER (PARTITION BYproduct ORDER BY ts, key DESC) AS ix FROMsales) AS q1

WHERE ix = 1;

为什么查询结果不同于上一次运行?在进行“快速修复”时,key列被放在了ORDER BY中的缺点位置。
它该当在DESC语句之后,而不是之前。
查询现在将返回第一笔发卖,而不是末了一笔发卖。
再进行一次改动。

SELECT product, price

FROM (SELECT product, price, row_number() OVER (PARTITION BYproduct ORDER BY ts DESC, key) AS ix FROMsales) AS q1

WHERE ix = 1;

本次修复使结果可重复。

来源:Pexels

这些都是大家常常踩雷的SQL缺点和解决方案。
不知道你是否也感同身受,或者还有其他有关SQL查询的趣事?记得给小芯分享哟~

留言点赞关注

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

如转载,请后台留言,遵守转载规范