Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -645,10 +645,16 @@ make_group_number_equal_count (arguments : Vector) = if arguments.length < 3 the

ordering_part = if ordering.length == 0 then "" else
SQL_Builder.code "ORDER BY " ++ SQL_Builder.join ", " ordering
count = SQL_Builder.code "(count(*) over ())"
row_number_minus_1 = SQL_Builder.code "((row_number() over (" ++ ordering_part ++ ")) - 1)"
group_size = SQL_Builder.code "(((count(*) over ()) + (" ++ group_count.paren ++ " - 1)) / " ++ group_count.paren ++ ")"
base_value = SQL_Builder.code "(" ++ row_number_minus_1 ++ " / " ++ group_size ++ " + 1)"
SQL_Builder.code "((" ++ base_value.paren ++ " * " ++ step.paren ++ ") + " ++ offset.paren ++ ")"
small_group_size = SQL_Builder.code "(" ++ count ++ " / " ++ group_count.paren ++ ")"
extra = SQL_Builder.code "(" ++ count ++ " % " ++ group_count.paren ++ ")"
is_in_large_groups = SQL_Builder.code "(" ++ row_number_minus_1 ++ " < (" ++ extra.paren ++ " * (" ++ small_group_size.paren ++ " + 1)))"
gn_large_groups = SQL_Builder.code "(" ++ row_number_minus_1 ++ " / (" ++ small_group_size.paren ++ " + 1))"
gn_small_groups = SQL_Builder.code "(((" ++ row_number_minus_1 ++ " - (" ++ extra.paren ++ " * (" ++ small_group_size.paren ++ " + 1))) / " ++ small_group_size.paren ++ ") + " ++ extra.paren ++ ")"
base_group_number = SQL_Builder.code "(case when " ++ is_in_large_groups.paren ++ " then " ++ gn_large_groups.paren ++ " else " ++ gn_small_groups.paren ++ " end)"

SQL_Builder.code "((" ++ base_group_number.paren ++ " * " ++ step.paren ++ ") + " ++ offset.paren ++ ")"

## ---
private: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,5 @@ make_group_number (from : Integer) (step : Integer) (grouping_expressions : Vect
private: true
---
make_group_number_equal_count (from : Integer) (step : Integer) (group_count : Integer) (ordering_expressions : Vector SQL_IR_Expression) -> SQL_IR_Expression =
# The SQL row_number() counts from 1, so we adjust the offset.
offset = (from - step) : Integer
params = [SQL_IR_Expression.Literal offset.to_text, SQL_IR_Expression.Literal step.to_text, SQL_IR_Expression.Literal group_count.to_text] + ordering_expressions
params = [SQL_IR_Expression.Literal from.to_text, SQL_IR_Expression.Literal step.to_text, SQL_IR_Expression.Literal group_count.to_text] + ordering_expressions
SQL_IR_Expression.Operation "GROUP_NUMBER_EQUAL_COUNT" params
Original file line number Diff line number Diff line change
Expand Up @@ -506,22 +506,26 @@ make_date_diff arguments (metadata : Date_Period_Metadata) =
## ---
private: true
---
GroupNumber = FLOOR(RowNumber / CEIL(TotalRowCount / GroupCount)) (0 based)
make_group_number_equal_count : Vector SQL_Builder -> SQL_Builder
make_group_number_equal_count (arguments : Vector) = if arguments.length < 3 then Error.throw (Illegal_State.Error "Wrong amount of parameters in GROUP_NUMBER_EQUAL_COUNT IR. This is a bug in the Database library.") else
ordering = arguments.drop 3
ordering_part = if ordering.length == 0 then "" else
SQL_Builder.code " OVER (ORDER BY " ++ SQL_Builder.join ", " ordering ++ ")"
row_number_minus_1 = (SQL_Builder.code "ROW_NUMBER()" ++ ordering_part).paren ++ " - 1"

offset = arguments.at 0
step = arguments.at 1
group_count = arguments.at 2
group_size = SQL_Builder.code "CEIL((COUNT(*) OVER ()) / " ++ group_count ++ ")"

base_value = SQL_Builder.code "FLOOR(" ++ row_number_minus_1.paren ++ " / " ++ group_size ++ ") + 1"
ordering = arguments.drop 3

offset = arguments.at 0
step = arguments.at 1
(base_value.paren ++ " * " ++ step) . paren ++ " + " ++ offset
ordering_part = if ordering.length == 0 then "" else
SQL_Builder.code "ORDER BY " ++ SQL_Builder.join ", " ordering
count = SQL_Builder.code "(count(*) over ())"
row_number_minus_1 = SQL_Builder.code "((row_number() over (" ++ ordering_part ++ ")) - 1)"
small_group_size = SQL_Builder.code "(floor(" ++ count ++ " / " ++ group_count.paren ++ "))"
extra = SQL_Builder.code "(" ++ count ++ " % " ++ group_count.paren ++ ")"
is_in_large_groups = SQL_Builder.code "(" ++ row_number_minus_1 ++ " < (" ++ extra.paren ++ " * (" ++ small_group_size.paren ++ " + 1)))"
gn_large_groups = SQL_Builder.code "(floor(" ++ row_number_minus_1 ++ " / (" ++ small_group_size.paren ++ " + 1)))"
gn_small_groups = SQL_Builder.code "(floor(((" ++ row_number_minus_1 ++ " - (" ++ extra.paren ++ " * (" ++ small_group_size.paren ++ " + 1))) / " ++ small_group_size.paren ++ ") + " ++ extra.paren ++ "))"
base_group_number = SQL_Builder.code "(case when " ++ is_in_large_groups.paren ++ " then " ++ gn_large_groups.paren ++ " else " ++ gn_small_groups.paren ++ " end)"

SQL_Builder.code "((" ++ base_group_number.paren ++ " * " ++ step.paren ++ ") + " ++ offset.paren ++ ")"

## ---
private: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -650,12 +650,16 @@ make_group_number_equal_count (arguments : Vector) = if arguments.length < 3 the

ordering_part = if ordering.length == 0 then "" else
SQL_Builder.code "ORDER BY " ++ SQL_Builder.join ", " ordering
count = SQL_Builder.code "(count(*) over ())"
row_number_minus_1 = SQL_Builder.code "((row_number() over (" ++ ordering_part ++ ")) - 1)"
group_size_f = SQL_Builder.code "(((count(*) over ()) + (" ++ group_count.paren ++ " - 1)) / " ++ group_count.paren ++ ")"
group_size = SQL_Builder.code "FLOOR(" ++ group_size_f.paren ++ ")"
base_value_f = SQL_Builder.code "(" ++ row_number_minus_1 ++ " / " ++ group_size ++ " + 1)"
base_value = SQL_Builder.code "FLOOR(" ++ base_value_f.paren ++ ")"
SQL_Builder.code "((" ++ base_value.paren ++ " * " ++ step.paren ++ ") + " ++ offset.paren ++ ")"
small_group_size = SQL_Builder.code "(floor(" ++ count ++ " / " ++ group_count.paren ++ "))"
extra = SQL_Builder.code "(" ++ count ++ " % " ++ group_count.paren ++ ")"
is_in_large_groups = SQL_Builder.code "(" ++ row_number_minus_1 ++ " < (" ++ extra.paren ++ " * (" ++ small_group_size.paren ++ " + 1)))"
gn_large_groups = SQL_Builder.code "(floor(" ++ row_number_minus_1 ++ " / (" ++ small_group_size.paren ++ " + 1)))"
gn_small_groups = SQL_Builder.code "(floor(((" ++ row_number_minus_1 ++ " - (" ++ extra.paren ++ " * (" ++ small_group_size.paren ++ " + 1))) / " ++ small_group_size.paren ++ ") + " ++ extra.paren ++ "))"
base_group_number = SQL_Builder.code "(case when " ++ is_in_large_groups.paren ++ " then " ++ gn_large_groups.paren ++ " else " ++ gn_small_groups.paren ++ " end)"

SQL_Builder.code "((" ++ base_group_number.paren ++ " * " ++ step.paren ++ ") + " ++ offset.paren ++ ")"

## ---
private: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ type Unique_Name_Strategy
private: true
advanced: true
---
Takes a name and gets a unique version.
Takes a name and gets a unique version. Marks the newly created name as
used.

## Arguments
- `name`: The column name to make unique.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,15 +65,20 @@ add_group_number_specs suite_builder setup =
g3 = t.add_group_number (..Equal_Count 5) "g"
g3.at 'g' . to_vector . should_equal [0, 0, 1, 1, 2, 2, 3, 3, 4]

big_t = table_builder [['x', (0.up_to (298*5 + 1)).to_vector]] . order_by ['x']
big_t_grouped = big_t.add_group_number (..Equal_Count 5) "g"
big_t_counted = big_t_grouped . aggregate "g" [Aggregate_Column.Count] . order_by "g"
big_t_counted.at 'Count' . to_vector . should_equal [299, 298, 298, 298, 298]

group_builder.specify "should add group number by equal counts, with order_by" <|
t = table_builder [['x', [1, 2, 3, 4, 5, 6, 7, 8, 9]], ['y', [9, 8, 7, 6, 5, 4, 3, 2, 1]]] . order_by ['x']

g0 = t.add_group_number (..Equal_Count 4 ['x']) "g" . sort ['x']
g0.at 'g' . to_vector . should_equal [0, 0, 0, 1, 1, 1, 2, 2, 2]
g0.at 'g' . to_vector . should_equal [0, 0, 0, 1, 1, 2, 2, 3, 3]
g0.at 'x' . to_vector . should_equal [1, 2, 3, 4, 5, 6, 7, 8, 9]

g1 = t.add_group_number (..Equal_Count 4 ['y']) "g" . sort ['y']
g1.at 'g' . to_vector . should_equal [0, 0, 0, 1, 1, 1, 2, 2, 2]
g1.at 'g' . to_vector . should_equal [0, 0, 0, 1, 1, 2, 2, 3, 3]
g1.at 'x' . to_vector . should_equal [9, 8, 7, 6, 5, 4, 3, 2, 1]

group_builder.specify "should add group number by unique values, with from and step" <|
Expand Down
Loading