SQL 为什么动不动就 N 百行以 K 计_oracle某支股票最长连续涨了多少交易日

1. 将数据按产品分组,将每组排序,取出前 10 名;

2. 将所有的前 10 名取交集;

由于我们事先不知道会有多个产品,这样需要把分组结果也存储在一个临时表中,而这个表有个字段要存储对应的分组成员,这是 SQL 不支持的,办法就行不通了。

如果有窗口函数的支持,可以转换思路,按产品分组后,计算每个销售员在所有分组的前 10 名中出现的次数,若与产品总数相同,则表示该销售员在所有产品销售额中均前在前 10 名内。

select sales
from ( select sales,
     from ( select sales,
                   rank() over (partition by product order by amount desc ) ranking
            from sales_amount)
     where ranking <=10 )
group by sales
having count(*)=(select count(distinct product) from sales_amount)

这样的 SQL,有多少人会写呢?

况且,窗口函数在有些数据库中还不支持。那么,就只能用存储过程写循环依次计算每个产品的前 10 名,与上一次结果做交集。这个过程比用高级语言编写程序并不简单多少,而且仍然要面向临时表的繁琐。

现在,我们知道了 SQL 的第二个重要缺点:集合化不彻底。虽然 SQL 有集合概念,但并未把集合作为一种基础数据类型提供,这使得大量集合运算在思维和书写时都需要绕路。

我们在上面的计算中使用了关键字 top,事实上关系代数理论中没有这个东西(它可以被别的计算组合出来),这不是 SQL 的标准写法。

我们来看一下没有 top 时找前 10 名会有多困难?

大体思路是这样:找出比自己大的成员个数作为是名次,然后取出名次不超过 10 的成员,写出的 SQL 如下:

select sales
from ( select A.sales sales, A.product product,
             (select count(*)+1 from sales_amount
              where A.product=product AND A.amount<=amount) ranking
       from sales_amount A )
where product='AC' AND ranking<=10

select sales
from ( select A.sales sales, A.product product, count(*)+1 ranking
       from sales_amount A, sales_amount B
       where A.sales=B.sales and A.product=B.product AND A.amount<=B.amount
       group by A.sales,A.product )
where product='AC' AND ranking<=10

这样的 SQL 语句,专业程序员写出来也未必容易吧!而仅仅是计算了一个前 10 名。

退一步讲,即使有 top,那也只是使取出前一部分轻松了。如果我们把问题改成取第 6 至 10 名,或者找比下一名销售额超过 10% 的销售员,困难仍然存在。

造成这个现象的原因就是 SQL 的第三个重要缺点:缺乏有序支持

SQL 继承了数学上的无序集合,这直接导致与次序有关的计算相当困难,而可想而知,与次序有关的计算会有多么普遍(诸如比上月、比去年同期、前 20%、排名等)。

SQL2003 标准中增加的窗口函数提供了一些与次序有关的计算能力,这使得上述某些问题可以有较简单的解法,在一定程度上缓解 SQL 的这个问题。但窗口函数的使用经常伴随着子查询,而不能让用户直接使用次序访问集合成员,还是会有许多有序运算难以解决。

我们现在想关注一下上面计算出来的“好”销售员的性别比例,即男女各有多少。一般情况下,销售员的性别信息会记在花名册上而不是业绩表上,简化如下:

</
employee 员工表
name 员工姓名,假定无重名
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值