您好,登錄后才能下訂單哦!
當分組聚合的結果集不大時,可以使用groups。例如有學生成績表存儲在集文件中,表結構如下:
Scores |
class |
studentID |
subject |
score |
…… |
?
現在計算每個學生的總分數:
A | |
1 | =file("scores.btx").import@b() |
2 | =A1.groups(studentID; ? sum(score):TotalScore) |
A1:成績表的數據裝入內存。
A2:按照studentID字段分組,計算總分。
?
如果成績表數據太大,無法裝入內存,則可以用游標方式:
A | |
1 | =file("scores.btx").cursor@b() |
2 | =A1.groups(studentID; ? sum(score):TotalScore) |
A1:得到成績表的游標。
A2:按照studentID字段分組,計算總分。
?
當成績表記錄很多,分組計算的結果集很大時,就要使用groupx:
A | |
1 | =file("scores.btx").cursor@b() |
2 | =A1.groupx(studentID; ? sum(score):TotalScore;10000) |
A1:得到成績表的游標。
A2:按照studentID字段分組,計算總分。
groupx的最后一個參數是緩沖區(qū)行數,也就是內存里能夠一次處理的記錄條數,這里指定為10000,實際使用時要根據自己的情況進行調整。
當數據對分組字段有序時,可以使用groups@o。如上例中,當成績表對studentID字段有序時,就可以加上選項o:
A | |
1 | =file("scores.btx").import@b() |
2 | =A1.groups@o(studentID; sum(score):TotalScore) |
?
如果成績表太大,無法裝入內存,可以使用游標:
A | |
1 | =file("scores.btx").cursor@b() |
2 | =A1.groups@o(studentID; sum(score):TotalScore) |
?
同樣,如果有序分組的結果集很大,就不能用groups,這時要使用group:
A | |
1 | =file("scores.btx").cursor@b() |
2 | =A1.group(studentID; sum(score):TotalScore) |
group的返回是游標,這一點跟groups不一樣。
?“后半”有序是指:要分組的表 T 已經對字段a,b有序,現在我們要將表T按字段b進行分組。例如有保存銷售記錄的集文件sale.btx,表結構如下:
Sales |
date |
employeeID |
amount |
…… |
銷售表對字段date,employeeID有序,現在要計算每個員工的銷售總額,對employeeID字段做分組,這時常規(guī)分組會計算hash,但這種后半有序的情況可以使用groups@h,看一下實現:
A | |
1 | =file("sale.btx").import@b() |
2 | =A1.groups@h(employeeID; ? sum(amount):TotalAmount) |
如果銷售表太大,無法裝入內存,可以使用游標:
A | |
1 | =file("sale.btx").cursor@b() |
2 | =A1.groups@h(employeeID; ? sum(amount):TotalAmount) |
?
當分組表達式的結果是序號的時候,可以使用groups@n。仍然使用上例的銷售表,現在要計算統(tǒng)計每個月的銷售額,實現是這樣的:
A | |
1 | =file("sale.btx").cursor@b() |
2 | =A1.groups@n0(month(date):MONTH;sum(amount): ? TotalAmount) |
A1:得到銷售表的游標。
A2:把date字段轉換為月份,計算每個月的銷售總額;如果存在date字段是null的情況,則要加上選項@0。
?
使用@n之后,會依據序號去分組,而不用再計算HASH,所以要比不帶@n時快。
使用3億條數據測試,本案例實際測試結果:
耗時(秒) | |
有 @n | 沒有 @n |
39 | 49 |
過濾拆分是指根據條件分組,滿足條件和不滿足條件的分成兩個集。使用select可以做到這種拆分,但是要遍歷兩次,即一次select(條件true),和一次select(條件false)。
而使用group和align只需要遍歷一次。以上面成績表為例,現在要把成績及格的和不及格的分成兩組,看一下group的實現:
A | |
1 | =file("scores.btx").import@b() |
2 | =A1.group(score>=60) |
?
需要注意的是,使用group過濾拆分的結果不一定是兩個集,有可能結果只有一個集,如本例中,有可能出現成績都大于60的情況。這時候需要判斷一下結果集的個數,或者使用align,因為align的結果肯定是兩個集,沒有符合條件的記錄,也會產生一個空集。來看一下align的實現:
?
?
A | |
1 | =file("scores.btx").import@b() |
2 | =A1.align@a([true,false],score>=60) |
?
如果想在過濾拆分中把不滿足的寫進文件,可以使用select(x;file),看一下實現:
A | |
1 | =file("scores.btx").cursor@b() |
2 | =A1.select (score>=60;file(“Fail.btx”)) |
3 | =A2.fetch() |
執(zhí)行完成后,A3里是成績及格的,不及格的會保存到集文件Fail.btx。
?
如果要拆分為多個集,可以使用groupn。例如要把成績分為優(yōu)秀、良好、及格和不及格這些集合,可以這樣實現:
A | |
1 | =file("scores.btx").cursor@b() |
2 | =[file(“Excellent.btx”), file(“Good.btx”), ? file(“Pass.btx”), file(“Fail.btx”)] |
3 | =A1.groupn(if(score>=90:1, ? score>=80:2, score>=60:3,4);A2) |
4 | =A3.fetch() |
top也可以用于group中,例如計算每個部門里薪水的最大值:
A | |
1 | =file("employee.btx").cursor@b() |
2 | =A1.groups(dept;top(-1,salary):MaxSalary) |
A1:得到員工表的游標。
A2:按照dept字段分組,組內再求最高薪水值,命名為topSalary。
?
A2執(zhí)行結果的MaxSalary字段是數值,如果想查詢薪水最高的員工的信息,可以寫成這樣:
A | |
1 | =file("employee.btx").cursor@b() |
2 | =A1.groups(dept;top(-1;salary):MaxSalary) |
?
top不僅可以返回最大值,還可以得到前n個最靠前的值,這時把1寫成n即可。例如計算每個部門里薪水排前三名的員工的信息:
A | |
1 | =file("employee.btx").cursor@b() |
2 | =A1.groups(dept;top(-3;salary):topSalary) |
?
使用groups進行分組計算時,還可以采取并行方式進一步提高性能,這時要加上選項@m。
如上面例中,計算每個員工的銷售總額,看一下并行方式的實現:
A | |
1 | =file("sale.btx").import@m() |
2 | =A1.groups@m(employeeID; sum(amount):TotalAmount) |
?
如果數據太大,無法裝入內存,可以使用多路游標:
A | |
1 | =file("sale.btx").cursor@mb() |
2 | =A1.groups@m(employeeID; sum(amount):TotalAmount) |
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。