偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

第25期:有序分組

企業(yè)動(dòng)態(tài)
我們知道,SQL延用了數(shù)學(xué)上的無(wú)序集合概念,所以SQL的分組并不關(guān)注過(guò)待分組集合中成員的次序,分組規(guī)則都是建立在成員取值本身上。

有序分組

我們知道,SQL延用了數(shù)學(xué)上的無(wú)序集合概念,所以SQL的分組并不關(guān)注過(guò)待分組集合中成員的次序。我們?cè)谇懊嬗懻撨^(guò)的等值分組和非等值分組,也都沒有關(guān)注過(guò)這個(gè)問題,分組規(guī)則都是建立在成員取值本身上。但如果我們要拓展SQL,以有序集合為考慮對(duì)象時(shí),那就必須考慮成員次序?qū)Ψ纸M的影響了,而且,現(xiàn)實(shí)業(yè)務(wù)中有大量的有序分組應(yīng)用場(chǎng)景。

1. 序號(hào)分組

一個(gè)簡(jiǎn)單的例子:將一個(gè)班的學(xué)生平均分成三份(假定人數(shù)能被3整除)。按我們?cè)谇懊嫠f(shuō)的分組定義,這也可以看成是一種分組,但這個(gè)運(yùn)算在SQL中卻很難寫出來(lái),因?yàn)榉纸M依據(jù)和成員取值沒有關(guān)系。

如果使用我們?cè)谇懊嬷v有序遍歷語(yǔ)法時(shí)的#符號(hào),這個(gè)問題就很容易解決了。

  1. A.group( (#-1)*3\A.len() )   // 按序號(hào)分成前1/3,中1/3,后1/3 
  2. A.group( (#-1)%3 )             // 還可以按序號(hào)每三個(gè)中取一個(gè)構(gòu)成分組子集 

用SQL實(shí)現(xiàn)這個(gè)運(yùn)算就麻煩很多,需要先用子查詢?cè)斐鲆粋€(gè)序號(hào),然后再執(zhí)行類似的分組規(guī)則。

上面這個(gè)例子中其實(shí)還沒有真正關(guān)注成員的次序,只是說(shuō)明了序號(hào)的作用,待分組集合的成員是其它次序時(shí)也可以得到可用的結(jié)果。

我們?cè)倏锤嗬印?/p>

處理文本日志時(shí),有些日志的基本單位不是1行,而可能是3行,即每個(gè)事件總是寫出3行文本,這并不是多罕見的情況。對(duì)付這種日志時(shí),就需要把文本每3行拆成一個(gè)分組子集,然后針對(duì)每個(gè)分組再進(jìn)行詳細(xì)的分析處理。這時(shí)要正確的分組運(yùn)算就必須依賴于待分組集合中成員(文本日志的行)的次序了。

入學(xué)考試之后,把學(xué)生按成績(jī)排序蛇行分拆成兩個(gè)班,即名次1,4,5,8,...在一個(gè),而2,3,6,7,...在另一個(gè)班,這樣能保證兩個(gè)班的平均名次是相同的。這個(gè)分組也可以用序號(hào)做出來(lái):

  1. A.sort@z(score).group(#%4<2

這里用的分組值不再是常見的普通數(shù)值,而是一個(gè)布爾量,相當(dāng)于按“真“值和“假”值分成兩個(gè)組,真值對(duì)應(yīng)***個(gè)班,假值對(duì)應(yīng)另一個(gè)班。本質(zhì)上講,這還是個(gè)等值分組,只是用到的分組值可以是任意泛型。

顯然,這個(gè)分組的正確性也嚴(yán)重依賴于待分組集成的成員次序。

順便說(shuō)一句,這又是一個(gè)只關(guān)注分組子集而不關(guān)心聚合值的例子。

按序號(hào)分組在很多情況下就是用序號(hào)來(lái)計(jì)算出分組依據(jù),然后就變成普通的等值分組了。那么有沒有不能簡(jiǎn)單地轉(zhuǎn)換成等值分組的情況呢?

2. 值變化分組

有一組嬰兒出生記錄,是按出生次序排序的,我們現(xiàn)在關(guān)心連續(xù)出生的同性別嬰兒數(shù)量超過(guò)5的有多少批?

簡(jiǎn)單想,這就是先GROUP,計(jì)算每組COUNT值,然后數(shù)出有幾個(gè)大于5的。后兩步很簡(jiǎn)單,問題是怎么GROUP?

直接按嬰兒性別分組當(dāng)然是不對(duì)的,必須考慮次序,依次掃描記錄,當(dāng)嬰兒性別發(fā)生變化時(shí)則產(chǎn)生一個(gè)新組。這種分組顯然沒法直接用等值分組做出來(lái)了。

我們可以提供一個(gè)有序分組方法來(lái)實(shí)現(xiàn)這種分組:當(dāng)考察值發(fā)生變化時(shí)就產(chǎn)生一個(gè)新的分組。

  1. A.group@o(gender).count(~.len()>5)   // @o選項(xiàng)表示分組值變化時(shí)將產(chǎn)生新分組。 

用SQL就麻煩很多,需要先造成中間標(biāo)志和變量來(lái)生成組的序號(hào),大概是這樣

  1. SELECT COUNT(*) FROM 
  2.    (SELECT ChangeNumber FROM 
  3.         (SELECT SUM(ChangeFlag) OVER (ORDER BY birthday) ChangeNumber FROM 
  4.             (SELECT CASE WHEN gender=LAG(gender) OVER ( ORDER BY birthday) THEN 0 ELSE 1 END ChangeFlag FROM A)) 
  5.     GROUP ChangeNumber HAVING COUNT(*)>5) 

這樣的SQL,看懂都不是很容易的。而且必須借助birthday這種字段來(lái)形成次序,而前述的有序分組寫法在原數(shù)據(jù)有序時(shí)根本用不著這個(gè)信息。

這種場(chǎng)景同樣可能出現(xiàn)在文本分析中。每個(gè)用戶的事件日志可能多行,而且行數(shù)不確定,但寫日志時(shí)會(huì)在每個(gè)行開始處寫上用戶號(hào)。這樣我們可以按這個(gè)用戶號(hào)進(jìn)行有序分組,它變化時(shí)就說(shuō)明是另一個(gè)用戶的事件了。

即使是普通的等值分組,如果事先知道原集合對(duì)分組字段有序,也可以使用這種方案來(lái)實(shí)施,這將獲得更高的性能,比數(shù)據(jù)庫(kù)常用的HASH分組方案要快得多,而且特別適合大數(shù)據(jù)遍歷的情況。

3. 條件變化分組

再看一個(gè)著名的問題:一支股票最長(zhǎng)連續(xù)上漲了多少天?

這個(gè)問題當(dāng)然可以直接遍歷去解決,不過(guò)我們現(xiàn)在用分組的思路來(lái)處理,至少在SQL體系下只能這么做(嚴(yán)格些說(shuō),這是目前找到的最簡(jiǎn)單可行的辦法)。

將股票收盤價(jià)按日期排序,然后將連續(xù)上漲的日期分到同一組,這樣只要考慮哪一組成員數(shù)最多即可。更明確地說(shuō),就是當(dāng)某天上漲了,就把這一天和前一天分到一個(gè)組中,某天下跌了,則產(chǎn)生一個(gè)新組。

用SQL實(shí)現(xiàn)這個(gè)思路,同樣需要用中間標(biāo)志和變量來(lái)生成組序號(hào):

  1. SELECT MAX(ContinuousDays) FROM 
  2.     (SELECT COUNT(*) ContinuousDays FROM 
  3.         (SELECT SUM(RisingFlag) OVER (ORDER BY TradingDate ) NoRisingDays FROM 
  4.             (SELECT TradingDate, 
  5.                 CASE WHEN ClosingPrice>LAG(ClosingPrice) OVER (ORDER BY TradingDate THEN 0 ELSE 1 END) RisingFlag 
  6.             FROM A)) 
  7.     GROUP BY NoRisingDays) 

如果有專門的有序分組方法以及以前說(shuō)過(guò)的有序遍歷語(yǔ)法,這個(gè)運(yùn)算就很簡(jiǎn)單了:

  1. A.sort(TradingDate).group@i(ClosingPrice<ClosingPrice[-1]).max(~.len())  //選項(xiàng)@i表示當(dāng)條件成立時(shí)產(chǎn)生新分組 

與SQL不同,雖然實(shí)現(xiàn)思路完全一樣,但寫出來(lái)是分步的,而不是一個(gè)多層嵌套語(yǔ)句,書寫和理解都要容易得多。

同樣地,這種場(chǎng)景也會(huì)在文本分析中有用。不確定行數(shù)的日志中,有時(shí)會(huì)在事件分始時(shí)寫一個(gè)標(biāo)志串,當(dāng)掃描到這個(gè)標(biāo)志串的時(shí)候就產(chǎn)生一個(gè)新的分組,有序分析的條件可設(shè)定為當(dāng)前掃描行和指定文字相同,這樣就能保證同一事件的日志信息在同一個(gè)組中。

后兩種有序分組的情況,理論上當(dāng)然也可以轉(zhuǎn)換成等值分組來(lái)處理(用SQL就要這么做,這也能從另一個(gè)側(cè)面說(shuō)明SQL運(yùn)算體系的完備性),但確實(shí)是相當(dāng)麻煩的,所以我們一般不把它再當(dāng)成等值分組來(lái)處理了。

到目前為止的分組討論,都是假定待分組集合已經(jīng)準(zhǔn)備好,其成員可以被隨機(jī)訪問到。但如果數(shù)據(jù)量巨大而不能全部讀入時(shí),如果繼續(xù)做這種假定,會(huì)導(dǎo)致頻繁的外存交換而性能極差,這時(shí)需要再設(shè)計(jì)以流方式邊讀入邊分組并且邊聚合的運(yùn)算體系。事實(shí)上日志分析中更常見的是這種情況,這些問題我們將再撰文研究,但基本方法思路仍然離不開上面這些內(nèi)容。

責(zé)任編輯:趙寧寧 來(lái)源: 51CTO專欄
相關(guān)推薦

2017-10-18 22:34:33

SQL等值分組有序分組

2017-09-13 08:45:33

遍歷SQL運(yùn)算

2017-12-26 15:33:24

JOINSQL運(yùn)算

2017-09-27 08:25:35

SQL等值分組運(yùn)算

2014-02-12 17:18:21

移動(dòng)技術(shù)半月刊

2013-01-21 13:41:59

IBMdW

2011-08-31 14:04:18

IPv6網(wǎng)絡(luò)·安全技術(shù)周刊

2017-09-05 22:34:24

遍歷SQL運(yùn)算

2018-01-18 20:47:18

CPU數(shù)據(jù)線程

2018-01-24 07:45:51

數(shù)據(jù)倍增分段列存

2017-11-08 06:18:43

JOINSQL運(yùn)算

2018-02-06 23:30:07

文件存儲(chǔ)數(shù)據(jù)

2017-05-25 08:56:22

硬盤性能特征

2017-12-10 22:42:50

JOINSQL運(yùn)算

2017-12-12 22:48:21

JOIN維度運(yùn)算

2017-11-15 06:36:25

JOINSQL運(yùn)算

2018-01-01 23:28:37

JOIN維度數(shù)據(jù)分析

2017-05-24 17:08:29

OLAP

2017-05-22 22:23:29

索引本質(zhì)排序

2018-01-10 15:25:43

JOIN維度SQL
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)