Window Functions

Window functions compute their result based on a sliding window frame, a set of rows that are somehow related to the current row. It allows you to work with both aggregate and non-aggregate values all at once.

The window functions have three types: aggregate functions, ranking functions and analytic functions. Aggregate functions: COUNT, AVERAGE, SUM, MAX, MIN, etc. Ranking functions: WRANK, ROWNUMBER, DENSERANK, WPERCENTRANK, CUMEDIST. Analytic functions: FIRSTVALUE, LASTVALUE, NTHVALUE, LEAD, LAG, NTILE. The aggregate functions don’t require ORDERBY, but they accept the window frame definition. ROWNUMBER Syntax Usage notes Returns the number of the current row within its partition. Row numbers range from 1 to the number of partition rows. It neither requires the ORDERBY nor accepts window frame definition. W_RANK Syntax Usage notes Returns the rank of each row within the partition of a result set. Peers are considered ties and receive the same rank. Requires ORDERBY, does not accept window frame definition. DENSERANK Syntax Usage notes Returns the rank of the current row within its partition, without gaps. Peers are considered ties and receive the same rank. Requires ORDERBY, does not accept window frame definition. W_PERCENTRANK Syntax Usage notes Calculates the percentage of the relative rank of a row within a partition of rows. Using the rank of the row and the number of the total rows to compute the percentage: rank-1 / rows -1. And the range is [0,1]. Requires ORDERBY, does not accept window frame definition. CUMEDIST Syntax Usage notes Cumulative distribution value. The number of rows with values be less than or equal to the current row’s value is divided by the total number of rows within the partition. And the range is (0,1]. Requires ORDERBY, does not accept window frame definition. LEAD Syntax Argument Description value_function (Required) The field name or formula. [offset_value] (Optional) Row offset after the current, offset = 1. [default_value] (Optional) default value, default = null Usage notes Provides access to the value from a row at a given physical offset that follows the current row. If these is no such row, the return value is the default value. Does not accept window frame definition. LAG Syntax Argument Description value_function (Required) The field name or formula. [offset_value] (Optional) Row offset before the current, offset = 1. [default_value] (Optional) default value, default = null Usage notes Provides access to the value from a row at a given physical offset that before the current row. If these is no such row, the return value is the default value. Does not accept window frame definition. NTILE Syntax Argument Description n (Required) The count of buckets. Usage notes Divides a partition into N buckets, assigns each row in the partition its bucket number. Does not accept window frame definition. FIRSTVALUE Syntax Argument Description value_function (Required) The field name or formula. Usage notes The value for the first row within the window frame. It does not require ORDERBY. LASTVALUE Syntax Argument Description value_function (Required) The field name or formula. Usage notes The value for the last row within the window frame. It does not require ORDERBY. NTHVALUE Syntax Argument Description value_function (Required) The field name or formula. n (Required) The n-th row within the window frame. Usage notes The value for the n-th row within the window frame. If there is no such row, the return value is null. It does not require ORDERBY.
/*REPLACE_MARKER*/ /*DO NOT DELETE THESE COMMENTS*/ window.onload = function () { var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"), { sheetCount: 0 }); initSpread(spread); }; function initSpread(spread) { spread.suspendPaint(); spread.clearSheets(); spread.options.autoFitType = GC.Spread.Sheets.AutoFitType.cellWithHeader; spread.options.allowDynamicArray = true; spread.options.highlightInvalidData = true; spread.options.calcOnDemand = true; ratioMedals(spread); countyMedals(spread); athleteDenseRankMedals(spread); employeeDepartmentPayRank(spread); saleDivideGroups(spread); timeToNextStation(spread); revenueTrends(spread); trainTravelTime(spread); spread.resumePaint(); } function ratioMedals(spread) { //init a data manager var dataManager = spread.dataManager(); var athleteMedalTable = dataManager.addTable("athleteMedalTable", { remote: { read: { url: "$DEMOROOT$/spread/source/data/olympic-athlete-medals.csv" } }, schema: { type: "csv", columns: { Medals: { dataType: "number" }, TotalMedals: { dataType: "formula", value: '=WINDOW(SUM([Medals]), "CountryMedals")' }, }, window: { CountryMedals: "=WINDOWDEF(PARTITIONBY([Country]), ORDERBY([Country], ORDERDESC([Medals])), FRAMEROWS(-1, -1))" } } }); //init a table sheet var sheet = spread.addSheetTab(0, "Ratio Of Medals", GC.Spread.Sheets.SheetType.tableSheet); sheet.setDefaultRowHeight(40, GC.Spread.Sheets.SheetArea.colHeader); sheet.options.allowAddNew = false; //hide new row //bind a view to the table sheet athleteMedalTable.fetch().then(function () { var myView = athleteMedalTable.addView("myView", [ { value: "Country", width: 100 }, { value: "Athlete", width: 80 }, { value: "Medals", width: 80 }, { value: "TotalMedals", caption: 'Total Medals', width: 150, style: { backColor: "#E2EFDA" } }, { value: "=[@Medals] / [@TotalMedals]", caption: 'Ratio Of Medals', width: 150, style: { backColor: "#E2EFDA", formatter: '0.00%' } }, ]); spread.suspendPaint(); sheet.setDataView(myView); spread.resumePaint(); }); } function countyMedals(spread) { //init a data manager var dataManager = spread.dataManager(); var countryMedalTable = dataManager.addTable("countryMedalTable", { remote: { read: { url: "$DEMOROOT$/spread/source/data/olympic-country-medals.csv" } }, schema: { type: "csv", columns: { Medals: { dataType: "number" }, } } }); //init a table sheet var sheet = spread.addSheetTab(1, "Country Medals Rank", GC.Spread.Sheets.SheetType.tableSheet); sheet.setDefaultRowHeight(40, GC.Spread.Sheets.SheetArea.colHeader); sheet.options.allowAddNew = false; //hide new row //bind a view to the table sheet countryMedalTable.fetch().then(function () { var myView = countryMedalTable.addView("myView", [ { value: "Country", width: 100 }, { value: "Medals", width: 80 }, { value: "=WINDOW(W_RANK(), ORDERBY(ORDERDESC([Medals])))", caption: 'Rank', width: 150, style: { backColor: "#E2EFDA" } }, ]); spread.suspendPaint(); sheet.setDataView(myView); spread.resumePaint(); }); } function athleteDenseRankMedals(spread) { //init a data manager var dataManager = spread.dataManager(); var athleteMedalTable = dataManager.addTable("athleteMedalRankTable", { remote: { read: { url: "$DEMOROOT$/spread/source/data/olympic-athlete-medals.csv" } }, schema: { type: "csv", columns: { Medals: { dataType: "number" }, } } }); //init a table sheet var sheet = spread.addSheetTab(2, "Athlete Medals Rank", GC.Spread.Sheets.SheetType.tableSheet); sheet.setDefaultRowHeight(40, GC.Spread.Sheets.SheetArea.colHeader); sheet.options.allowAddNew = false; //hide new row //bind a view to the table sheet athleteMedalTable.fetch().then(function () { var myView = athleteMedalTable.addView("myView", [ { value: "=WINDOW(ROWNUMBER(), PARTITIONBY([Country]))", caption: 'No.', width: 70, style: { backColor: "#E2EFDA" } }, { value: "Country", width: 100 }, { value: "Athlete", width: 80 }, { value: "Medals", width: 80 }, { value: "=WINDOW(DENSERANK(), PARTITIONBY([Country]), ORDERBY(ORDERDESC([Medals])))", caption: 'Rank', width: 150, style: { backColor: "#E2EFDA" } }, ]); spread.suspendPaint(); sheet.setDataView(myView); spread.resumePaint(); }); } function employeeDepartmentPayRank(spread) { //init a data manager var dataManager = spread.dataManager(); var employeeDepartmentPayTable = dataManager.addTable("employeeDepartmentPayTable", { remote: { read: { url: "$DEMOROOT$/spread/source/data/employee-department-pay.csv" } }, schema: { type: "csv", window: { DepartmentRate: "=WINDOWDEF(PARTITIONBY([Department]), ORDERBY([Rate]))" } } }); //init a table sheet var sheet = spread.addSheetTab(3, "Employee Pay Rank", GC.Spread.Sheets.SheetType.tableSheet); sheet.setDefaultRowHeight(40, GC.Spread.Sheets.SheetArea.colHeader); sheet.options.allowAddNew = false; //hide new row //bind a view to the table sheet employeeDepartmentPayTable.fetch().then(function () { var myView = employeeDepartmentPayTable.addView("myView", [ { value: "Department", width: 120 }, { value: "LastName", width: 120 }, { value: "Rate", width: 80 }, // The CUMEDIST returns a value that represents the percent of employees with a salary less than or equal to the current employee in the same department. { value: "=WINDOW(CUMEDIST(), \"DepartmentRate\")", caption: 'Salary % ( <= current)', width: 180, style: { backColor: "#E2EFDA", formatter: '0.00' } }, // The W_PERCENTRANK function calculates the percent rank of the employee's salary within a department. { value: "=WINDOW(W_PERCENTRANK(), \"DepartmentRate\")", caption: 'Salary %', width: 140, style: { backColor: "#E2EFDA", formatter: '0.00' } }, ]); spread.suspendPaint(); sheet.setDataView(myView); spread.resumePaint(); }); } function timeToNextStation(spread) { //init a data manager var dataManager = spread.dataManager(); var timeToNextStationTable = dataManager.addTable("timeToNextStationTable", { remote: { read: { url: "$DEMOROOT$/spread/source/data/train-details.csv" } }, schema: { type: "csv", columns: { TrainNo: { dataName: 'Train No', dataType: 'number' }, TrainName: { dataName: 'Train Name' }, ArrivalTime: { dataName: 'Arrival time' }, DepartureTime: { dataName: 'Departure Time', }, LeadArrivalTime: { dataType: 'formula', value: '=WINDOW(LEAD([@ArrivalTime]), PARTITIONBY([TrainNo]))' }, } } }); //init a table sheet var sheet = spread.addSheetTab(4, "Time To Next Station", GC.Spread.Sheets.SheetType.tableSheet); sheet.setDefaultRowHeight(40, GC.Spread.Sheets.SheetArea.colHeader); sheet.options.allowAddNew = false; //hide new row //bind a view to the table sheet timeToNextStationTable.fetch().then(function () { var myView = timeToNextStationTable.addView("myView", [ { value: "TrainNo", caption: "Train No", width: 120 }, { value: "TrainName", caption: "Train Name", width: 120 }, { value: "ArrivalTime", caption: "Arrival Time", width: 120 }, { value: "DepartureTime", caption: "Departure Time", width: 150 }, { value: "=IF(ISBLANK([@LeadArrivalTime]), 0 ,TIMEVALUE([@LeadArrivalTime]) - TIMEVALUE([@DepartureTime]))", caption: "Time To Next Station", width: 180, style: { backColor: "#E2EFDA", formatter: 'h:mm:ss;@' } }, { value: '=TIMEVALUE([@ArrivalTime]) - WINDOW(MIN(MAP([ArrivalTime], LAMBDA(time,TIMEVALUE(time)))), PARTITIONBY([TrainNo]))', caption: "Elapsed Travel Time", width: 180, style: { backColor: "#E2EFDA", formatter: 'h:mm:ss;@' } }, ]); spread.suspendPaint(); sheet.setDataView(myView); spread.resumePaint(); }); } function revenueTrends(spread) { //init a data manager var dataManager = spread.dataManager(); var revenueTrendsTable = dataManager.addTable("revenueTrendsTable", { data: orderYearProductDataSource, schema: { type: "csv", columns: { Quantity: { dataType: "number" }, Amount: { dataType: "number" }, PreviousRevenue: { dataType: "formula", value: '=WINDOW(LAG([@Amount]), "ProductYear")' } }, window: { ProductYear: "=WINDOWDEF(PARTITIONBY([Product]), ORDERBY([Year]))" } } }); //init a table sheet var sheet = spread.addSheetTab(5, "Revenue Trends", GC.Spread.Sheets.SheetType.tableSheet); sheet.setDefaultRowHeight(40, GC.Spread.Sheets.SheetArea.colHeader); sheet.options.allowAddNew = false; //hide new row //bind a view to the table sheet revenueTrendsTable.fetch().then(function () { var myView = revenueTrendsTable.addView("myView", [ { value: "YEAR", width: 150 }, { value: "Product", width: 105 }, { value: "Amount", caption: "Revenue", width: 100, style: { formatter: "#,##0.00" } }, { value: "PreviousRevenue", caption: 'Previous Revenue', width: 180, style: { backColor: "#E2EFDA", formatter: "#,##0.00" } }, { value: "=[@Amount] - IF(ISBLANK([@PreviousRevenue]), 0, [@PreviousRevenue])", caption: 'Revenue Trends', width: 150, style: { backColor: "#E2EFDA", formatter: "#,##0.00" } }, ]); spread.suspendPaint(); sheet.setDataView(myView); spread.resumePaint(); }); } function saleDivideGroups(spread) { //init a data manager var dataManager = spread.dataManager(); var saleYearToDateDivideGroupTable = dataManager.addTable("saleYearToDateDivideGroupTable", { remote: { read: { url: "$DEMOROOT$/spread/source/data/sale-ytd.csv" } }, schema: { type: "csv", columns: { SalesYTD: { dataType: "number" }, } } }); //init a table sheet var sheet = spread.addSheetTab(6, "Sale Groups", GC.Spread.Sheets.SheetType.tableSheet); sheet.setDefaultRowHeight(40, GC.Spread.Sheets.SheetArea.colHeader); sheet.options.allowAddNew = false; //hide new row //bind a view to the table sheet saleYearToDateDivideGroupTable.fetch().then(function () { var myView = saleYearToDateDivideGroupTable.addView("myView", [ { value: "City", width: 100 }, { value: "FirstName", width: 100 }, { value: "LastName", width: 100 }, // It divides rows into four groups of employees based on their year-to-date sales { value: "=WINDOW(NTILE(4), PARTITIONBY([City]), ORDERBY(ORDERDESC([SalesYTD])))", caption: 'Quartile', width: 100, style: { backColor: "#E2EFDA" } }, { value: "SalesYTD", caption: 'Sales', width: 100, style: { formatter: "$#,##0.00" } }, ]); spread.suspendPaint(); sheet.setDataView(myView); spread.resumePaint(); }); } function trainTravelTime(spread) { //init a data manager var dataManager = spread.dataManager(); var trainTravelTimeTable = dataManager.addTable("trainTravelTimeTable", { remote: { read: { url: "$DEMOROOT$/spread/source/data/train-details.csv" } }, schema: { type: "csv", columns: { TrainNo: { dataName: 'Train No', dataType: 'number' }, TrainName: { dataName: 'Train Name' }, ArrivalTime: { dataName: 'Arrival time' }, DepartureTime: { dataName: 'Departure Time', }, LastArrivalTime: { dataType: 'formula', value: '=WINDOW(LASTVALUE(TIMEVALUE([@ArrivalTime])), PARTITIONBY([TrainNo]))' }, FirstDepartureTime: { dataType: 'formula', value: '=WINDOW(FIRSTVALUE(TIMEVALUE([@DepartureTime])), PARTITIONBY([TrainNo]))' }, ForthArrivalTime: { dataType: 'formula', value: '=WINDOW(NTHVALUE(TIMEVALUE([@ArrivalTime]), 4), PARTITIONBY([TrainNo]))' }, SecondArrivalTime: { dataType: 'formula', value: '=WINDOW(NTHVALUE(TIMEVALUE([@DepartureTime]), 2), PARTITIONBY([TrainNo]))' }, } } }); //init a table sheet var sheet = spread.addSheetTab(7, "Train Travel Time", GC.Spread.Sheets.SheetType.tableSheet); sheet.setDefaultRowHeight(40, GC.Spread.Sheets.SheetArea.colHeader); sheet.options.allowAddNew = false; //hide new row //bind a view to the table sheet trainTravelTimeTable.fetch().then(function () { var myView = trainTravelTimeTable.addView("myView", [ { value: "TrainNo", caption: "Train No", width: 120 }, { value: "TrainName", caption: "Train Name", width: 120 }, { value: "ArrivalTime", caption: "Arrival Time", width: 120 }, { value: "DepartureTime", caption: "Departure Time", width: 150 }, { value: '=[@LastArrivalTime] - [@FirstDepartureTime]', caption: "Max Travel Time", width: 150, style: { backColor: "#E2EFDA", formatter: 'h:mm:ss;@' } }, { value: "=[@ForthArrivalTime] - [@SecondArrivalTime]", caption: "2nd - 4th Station Travel Time", width: 220, style: { backColor: "#E2EFDA", formatter: 'h:mm:ss;@' } }, ]); spread.suspendPaint(); sheet.setDataView(myView); spread.resumePaint(); }); }
<!doctype html> <html style="height:100%;font-size:14px;"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <!-- Promise Polyfill for IE, https://www.npmjs.com/package/promise-polyfill --> <script src="https://cdn.jsdelivr.net/npm/promise-polyfill@8/dist/polyfill.min.js"></script> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets/dist/gc.spread.sheets.all.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-tablesheet/dist/gc.spread.sheets.tablesheet.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/spread/source/data/orderDataSource.js" type="text/javascript"></script> <script src="$DEMOROOT$/spread/source/data/orderYearProductDataSource.js" type="text/javascript"></script> <script src="$DEMOROOT$/spread/source/js/license.js" type="text/javascript"></script> <script src="app.js" type="text/javascript"></script> <link rel="stylesheet" type="text/css" href="styles.css"> </head> <body> <div class="sample-tutorial"> <div id="ss" class="sample-spreadsheets"></div> </div> </html>
.sample-tutorial { position: relative; height: 100%; overflow: hidden; } body { position: absolute; top: 0; bottom: 0; left: 0; right: 0; margin: 0; } .sample-spreadsheets { width: 100%; height: 100%; overflow: hidden; float: left; } .container { width: 300px; height: 100%; float: left; border: 1px solid lightgrey; }