在谈集合之前,需要先谈谈离散性的概念:
所谓离散性,是指集合的成员可以游离在集合之外存在并参与运算,游离成员还可以再组成新的集合。从离散性的解释上可以知道,离散性是针对集合而言的一种能力,离开集合概念单独谈离散性就没有意义了。
离散性是个很简单的特性,几乎所有支持结构(对象)的高级语言都天然支持,比如我们用Java时都可以把数组成员取出来单独计算,也可以再次组成新的数组进行集合运算(不过Java几乎没有提供集合运算类库)。
打个通俗的比方:假设有一个盒子里装满了白色小球,针对离散性的操作就相当于把盒子打开,把里面的小球一个个单独拿出来刷上不同颜色,则操作后每个小球的颜色都各不相同;而针对整个集合的操作,就相当于把装入一定数量小球的盒子,运到某个地方,则盒内所有小球也都同时被运到了那个地方。
回到程序的编写方向上,同时具备良好的集合运算类库与离散性引用机制的集算器脚本语言,相较于传统的SQL语言(受限于关系代数),无论从思考方式还是从执行效率上来看,都有着先天的优势。
一、解决一些逻辑稍微复杂一点的实际问题。
比如以前提到的:计算至少连涨四天的股票,在至少连涨三天的股票中所占的比例:
一个比较普通的思路是用窗口函数:将数据按公司名分区后再按日期排序(Order By),调用LAG窗口函数向上做求差运算并根据是否为负记是否为NULL,调用LAG和LEAD窗口函数找出上升趋势和下降趋势的分段点并记1,再调用SUM窗口函数将分段点预设值累加从而成为分段的依据字段,然后清空之前用NULL标记的无效行后,再分别统计算出>=3和>=4的数目,最后算出一个比值。
具体实现代码如下(下面以SqlServer数据库为例):
WITH T1 AS
(
SELECT T.COM COM, T.STA STA, SUM(T.FLG) OVER(PARTITION BY T.COM ORDER BY T.DAT) GRP
FROM (
SELECT [Company] COM, [Date] DAT, [Price] PRI,
CASE WHEN [Price] > LAG([Price],1,0) OVER(PARTITION BY [Company] ORDER BY [Date])
THEN 1 ELSE NULL END STA,
CASE WHEN [Price] < LAG([Price],1,0) OVER(PARTITION BY [Company] ORDER BY [Date])
AND [Price] < LEAD([Price],1,9999999) OVER(PARTITION BY [Company] ORDER BY [Date])
THEN 1 ELSE 0 END FLG
FROM Stock
) T
),
T2 AS
(
SELECT T1.COM COM, T1.GRP GRP, COUNT(T1.COM) CNT FROM T1 WHERE T1.STA IS NOT NULL GROUP BY T1.COM, T1.GRP
),
T3 AS