/* * cume_dist * return fraction betweeen 0 and 1 inclusive, * which is described as NP / NR, where NP is the number of rows preceding or * peers to the current row, and NR is the total number of rows, per spec. */ datum_t window_cume_dist(PG_FUNC_ARGS) { winobj_s* winobj = PG_WINOBJ(); rank_context *context; bool up; int64 totalrows = win_get_row_count(winobj); ASSERT(totalrows > 0); up = rank_up(winobj); context = (rank_context *) win_get_partition(winobj, sizeof(rank_context)); if (up || context->rank == 1) { /* * The current row is not peer to prior row or is just the first, so * count up the number of rows that are peer to the current. */ int64 row; context->rank = win_get_current_position(winobj) + 1; /* * start from current + 1 */ for (row = context->rank; row < totalrows; row++) { if (!win_rows_are_peers(winobj, row - 1, row)) break; context->rank++; } } RET_FLOAT8((float8) context->rank / (float8) totalrows); }
/* * dense_rank * Rank increases by 1 when key columns change. */ datum_t window_dense_rank(PG_FUNC_ARGS) { winobj_s* winobj = PG_WINOBJ(); rank_context *context; bool up; up = rank_up(winobj); context = (rank_context*) win_get_partition(winobj, sizeof(rank_context)); if (up) context->rank++; RET_INT64(context->rank); }
/* * rank * Rank changes when key columns change. * The new rank number is the current row number. */ Datum window_rank(PG_FUNCTION_ARGS) { WindowObject winobj = PG_WINDOW_OBJECT(); rank_context *context; bool up; up = rank_up(winobj); context = (rank_context *) WinGetPartitionLocalMemory(winobj, sizeof(rank_context)); if (up) context->rank = WinGetCurrentPosition(winobj) + 1; PG_RETURN_INT64(context->rank); }
/* * percent_rank * return fraction between 0 and 1 inclusive, * which is described as (RK - 1) / (NR - 1), where RK is the current row's * rank and NR is the total number of rows, per spec. */ datum_t window_percent_rank(PG_FUNC_ARGS) { winobj_s* winobj = PG_WINOBJ(); rank_context *context; bool up; int64 totalrows = win_get_row_count(winobj); ASSERT(totalrows > 0); up = rank_up(winobj); context = (rank_context*) win_get_partition(winobj, sizeof(rank_context)); if (up) context->rank = win_get_current_position(winobj) + 1; /* return zero if there's only one row, per spec */ if (totalrows <= 1) RET_FLOAT8(0.0); RET_FLOAT8((float8) (context->rank - 1) / (float8) (totalrows - 1)); }
/* * percent_rank * return fraction between 0 and 1 inclusive, * which is described as (RK - 1) / (NR - 1), where RK is the current row's * rank and NR is the total number of rows, per spec. */ Datum window_percent_rank(PG_FUNCTION_ARGS) { WindowObject winobj = PG_WINDOW_OBJECT(); rank_context *context; bool up; int64 totalrows = WinGetPartitionRowCount(winobj); Assert(totalrows > 0); up = rank_up(winobj); context = (rank_context *) WinGetPartitionLocalMemory(winobj, sizeof(rank_context)); if (up) context->rank = WinGetCurrentPosition(winobj) + 1; /* return zero if there's only one row, per spec */ if (totalrows <= 1) PG_RETURN_FLOAT8(0.0); PG_RETURN_FLOAT8((float8) (context->rank - 1) / (float8) (totalrows - 1)); }
/* * cume_dist * return fraction betweeen 0 and 1 inclusive, * which is described as NP / NR, where NP is the number of rows preceding or * peers to the current row, and NR is the total number of rows, per spec. */ Datum window_cume_dist(PG_FUNCTION_ARGS) { WindowObject winobj = PG_WINDOW_OBJECT(); rank_context *context; bool up; int64 totalrows = WinGetPartitionRowCount(winobj); Assert(totalrows > 0); up = rank_up(winobj); context = (rank_context *) WinGetPartitionLocalMemory(winobj, sizeof(rank_context)); if (up || context->rank == 1) { /* * The current row is not peer to prior row or is just the first, so * count up the number of rows that are peer to the current. */ int64 row; context->rank = WinGetCurrentPosition(winobj) + 1; /* * start from current + 1 */ for (row = context->rank; row < totalrows; row++) { if (!WinRowsArePeers(winobj, row - 1, row)) break; context->rank++; } } PG_RETURN_FLOAT8((float8) context->rank / (float8) totalrows); }