This is an automated email from the ASF dual-hosted git repository.

avamingli pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudberry.git


The following commit(s) were added to refs/heads/main by this push:
     new b8c6a63d61d Implement parallel processing for window functions.
b8c6a63d61d is described below

commit b8c6a63d61d844507aec598af8f6a6ba4f0d115b
Author: Zhang Mingli <[email protected]>
AuthorDate: Mon Jul 28 22:23:07 2025 +0800

    Implement parallel processing for window functions.
    
    PostgreSQL's parallel processing cannot handle window functions. In
    contrast, our distributed environment enables parallel execution of
    window functions across multiple processes on multiple segments.
    For example:
      sum(a) over(partition by b order by c)
    The window function can be processed by redistributing data
    based on column b to ensure all rows with the same b value are processed
    by the same worker, significantly improving efficiency.
    
    Even without PARTITION BY clauses, we can still enable parallelism by
    allowing partial_path for window functions and subpaths, with parallel
    scanning of underlying tables for data filtering.
    
    Exclude CASE WHEN expressions in window functions (as they
    complicate parallelization and make it difficult to guarantee correct
    data ordering)
    
    Example non-parallel execution plan:
    SELECT sum(salary) OVER w, rank() OVER w FROM empsalary WINDOW w AS
    (PARTITION BY depname ORDER BY salary DESC);
                      QUERY PLAN
    ----------------------------------------------
     Gather Motion 3:1  (slice1; segments: 3)
       ->  WindowAgg
             Partition By: depname
             Order By: salary
             ->  Sort
                   Sort Key: depname, salary DESC
                   ->  Seq Scan on empsalary
    
    Parallel execution plan (4-parallel):
    SELECT sum(salary) OVER w, rank() OVER w FROM empsalary WINDOW w AS
    (PARTITION BY depname ORDER BY salary DESC);
                                 QUERY PLAN
    ---------------------------------------------------------------------
     Gather Motion 12:1  (slice1; segments: 12)
       ->  WindowAgg
             Partition By: depname
             Order By: salary
             ->  Sort
                   Sort Key: depname, salary DESC
                   ->  Redistribute Motion 12:12  (slice2; segments: 12)
                         Hash Key: depname
                         Hash Module: 3
                         ->  Parallel Seq Scan on empsalary
    
    In complex queries containing window functions, parallel processing may
    sometimes be inhibited due to cost considerations or other constraints.
    However, our approach still provides valuable parallelization
    opportunities for window function subpaths, delivering measurable query
    efficiency improvements. We have observed significant performance gains
    in TPC-DS benchmarks through this partial parallelization capability.
    
    TPC-DS queries via parallel execution plans (50G AOCS, 4 workers):
    
    | Query | Before(ms) | After(ms) | Saved(ms) | Gain  | Plan Change     |
    |-------|-----------:|----------:|----------:|------:|-----------------|
    | q12   |  10,439.08 |  4,613.52 |  5,825.56 | 55.8% | serial→parallel |
    | q20   |  21,487.08 |  8,723.74 | 12,763.34 | 59.4% | serial→parallel |
    | q44   |  33,816.75 | 22,515.03 | 11,301.72 | 33.4% | better parallel |
    | q49   |  60,039.45 | 28,603.51 | 31,435.95 | 52.4% | serial→parallel |
    | q98   |  40,114.21 | 17,052.78 | 23,061.43 | 57.5% | serial→parallel |
    
    changes:
    - Enabled parallel plans for q12/q20/q49/q98 (prev. serial)
    - Optimized parallel plan for q44
    - Avg gain: 52% (best: q20 59.4%, saved 12.7s)
    
    Authored-by: Zhang Mingli [email protected]
---
 src/backend/cdb/cdbgroupingpaths.c                 |   5 +-
 src/backend/cdb/cdbpath.c                          |   2 +-
 src/backend/optimizer/plan/planner.c               | 165 ++++
 src/backend/optimizer/util/clauses.c               |   8 +-
 src/test/regress/expected/cluster.out              |   6 +-
 src/test/regress/expected/select_parallel.out      |  18 +-
 .../expected/statement_mem_for_windowagg.out       |   2 +
 src/test/regress/expected/window.out               | 308 ++++----
 src/test/regress/expected/window_optimizer.out     | 698 +++++++++--------
 src/test/regress/expected/window_parallel.out      | 869 +++++++++++++++++++++
 src/test/regress/greenplum_schedule                |   3 +
 src/test/regress/sql/cluster.sql                   |   6 +-
 src/test/regress/sql/select_parallel.sql           |   1 +
 .../regress/sql/statement_mem_for_windowagg.sql    |   2 +
 src/test/regress/sql/window.sql                    |  32 +-
 src/test/regress/sql/window_parallel.sql           | 223 ++++++
 16 files changed, 1813 insertions(+), 535 deletions(-)

diff --git a/src/backend/cdb/cdbgroupingpaths.c 
b/src/backend/cdb/cdbgroupingpaths.c
index 2462cd5e9b0..7ed1fec34b9 100644
--- a/src/backend/cdb/cdbgroupingpaths.c
+++ b/src/backend/cdb/cdbgroupingpaths.c
@@ -2651,7 +2651,7 @@ cdb_prepare_path_for_sorted_agg(PlannerInfo *root,
                return subpath;
        }
 
-       if (is_sorted && group_pathkeys)
+       if (is_sorted && group_pathkeys && (subpath->locus.parallel_workers <= 
1))
        {
                /*
                 * The input is already conveniently sorted. We could 
redistribute
@@ -2665,7 +2665,8 @@ cdb_prepare_path_for_sorted_agg(PlannerInfo *root,
                                                                                
         group_pathkeys,
                                                                                
         false, locus);
        }
-       else if (!is_sorted && group_pathkeys)
+       else if ((is_sorted && group_pathkeys && 
(subpath->locus.parallel_workers > 1)) ||
+               (!is_sorted && group_pathkeys))
        {
                /*
                 * If we need to redistribute, it's usually best to redistribute
diff --git a/src/backend/cdb/cdbpath.c b/src/backend/cdb/cdbpath.c
index d19bb141a4b..89d15437661 100644
--- a/src/backend/cdb/cdbpath.c
+++ b/src/backend/cdb/cdbpath.c
@@ -3661,7 +3661,7 @@ cdbpath_motion_for_parallel_join(PlannerInfo *root,
                int sp; /* small rel parallel workers */
                
                /* Consider locus when parallel_ware. */
-               if(parallel_aware)
+               if (parallel_aware)
                {
                        /* can't parallel join if both are Hashed, it should be 
in non-parallel path */
                        if (CdbPathLocus_IsHashed(outer.locus) &&
diff --git a/src/backend/optimizer/plan/planner.c 
b/src/backend/optimizer/plan/planner.c
index 463b24ba903..9728f4f34ef 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -300,6 +300,20 @@ static split_rollup_data 
*make_new_rollups_for_hash_grouping_set(PlannerInfo *ro
                                                                                
                                                 Path *path,
                                                                                
                                                 grouping_sets_data *gd);
 
+static bool
+contain_case_expr(Node *clause);
+
+static bool
+contain_case_expr_walker(Node *node, void *context);
+
+static void create_partial_window_path(PlannerInfo *root,
+                                                                               
        RelOptInfo *window_rel,
+                                                                               
        Path *path,
+                                                                               
        PathTarget *input_target,
+                                                                               
        PathTarget *output_target,
+                                                                               
        WindowFuncLists *wflists,
+                                                                               
        List *activeWindows);
+
 
 /*****************************************************************************
  *
@@ -4876,6 +4890,27 @@ create_window_paths(PlannerInfo *root,
                                                                   
activeWindows);
        }
 
+       /*
+        * Unlike Upstream, we could make window function parallel by 
redistributing
+        * the tuples according to the PARTITION BY clause which is similar to 
Group By.
+        * Even there is no PARTITION BY, window function could be parallel from
+        * sub partial paths.
+        */
+       if (window_rel->consider_parallel &&
+               input_rel->partial_pathlist)
+       {
+               /* For partial, only the best one if enough. */
+               Path       *path = (Path *) 
linitial(input_rel->partial_pathlist);
+
+               create_partial_window_path(root,
+                                                          window_rel,
+                                                          path,
+                                                          input_target,
+                                                          output_target,
+                                                          wflists,
+                                                          activeWindows);
+       }
+
        /*
         * If there is an FDW that's responsible for all baserels of the query,
         * let it consider adding ForeignPaths.
@@ -9103,3 +9138,133 @@ make_new_rollups_for_hash_grouping_set(PlannerInfo      
  *root,
 
        return srd;
 }
+
+static bool
+contain_case_expr(Node *clause)
+{
+       return contain_case_expr_walker(clause, NULL);
+}
+
+static bool
+contain_case_expr_walker(Node *node, void *context)
+{
+       if (node == NULL)
+               return false;
+
+       if (IsA(node, CaseExpr))
+               return true;
+
+       return expression_tree_walker(node, contain_case_expr_walker,
+                                                                 context);
+}
+
+/*
+ * Parallel processing of window functions.
+ *
+ * NB: it may produce non-deterministic results if the window function
+ * lacks ORDER BY and PARTITION BY clause.
+ * SQL:2011 has clarified this behavior.
+ */
+static void
+create_partial_window_path(PlannerInfo *root,
+                                          RelOptInfo *window_rel,
+                                          Path *path,
+                                          PathTarget *input_target,
+                                          PathTarget *output_target,
+                                          WindowFuncLists *wflists,
+                                          List *activeWindows)
+{
+       PathTarget *window_target;
+       ListCell   *l;
+       Bitmapset  *sgrefs;
+
+       window_target = input_target;
+
+       sgrefs = NULL;
+
+       foreach(l, activeWindows)
+       {
+               WindowClause *wc = lfirst_node(WindowClause, l);
+               ListCell   *lc2;
+
+               foreach(lc2, wc->partitionClause)
+               {
+                       SortGroupClause *sortcl = lfirst_node(SortGroupClause, 
lc2);
+
+                       sgrefs = bms_add_member(sgrefs, 
sortcl->tleSortGroupRef);
+               }
+               foreach(lc2, wc->orderClause)
+               {
+                       SortGroupClause *sortcl = lfirst_node(SortGroupClause, 
lc2);
+
+                       sgrefs = bms_add_member(sgrefs, 
sortcl->tleSortGroupRef);
+               }
+       }
+
+       int x = -1;
+       while ((x = bms_next_member(sgrefs, x)) >= 0)
+       {
+               Index   sgref = get_pathtarget_sortgroupref(input_target, x);
+               if (sgref != 0)
+               {
+                       ListCell   *lc;
+                       foreach(lc, input_target->exprs)
+                       {
+                               Expr    *expr = (Expr *) lfirst(lc);
+                               if (contain_case_expr((Node*)expr))
+                                       return;
+                       }
+               }
+       }
+
+       foreach(l, activeWindows)
+       {
+               WindowClause *wc = lfirst_node(WindowClause, l);
+               List       *window_pathkeys;
+               int                     presorted_keys;
+               bool            is_sorted;
+
+               window_pathkeys = make_pathkeys_for_window(root,
+                                                                               
                   wc,
+                                                                               
                   root->processed_tlist);
+
+               is_sorted = pathkeys_count_contained_in(window_pathkeys,
+                                                                               
                path->pathkeys,
+                                                                               
                &presorted_keys);
+
+               path = cdb_prepare_path_for_sorted_agg(root,
+                                                                               
           is_sorted,
+                                                                               
           presorted_keys,
+                                                                               
           window_rel,
+                                                                               
           path,
+                                                                               
           path->pathtarget,
+                                                                               
           window_pathkeys,
+                                                                               
           -1.0,
+                                                                               
           wc->partitionClause,
+                                                                               
           NIL);
+               if (lnext(activeWindows, l))
+               {
+                       ListCell   *lc2;
+
+                       window_target = copy_pathtarget(window_target);
+                       foreach(lc2, wflists->windowFuncs[wc->winref])
+                       {
+                               WindowFunc *wfunc = lfirst_node(WindowFunc, 
lc2);
+
+                               add_column_to_pathtarget(window_target, (Expr 
*) wfunc, 0);
+                               window_target->width += 
get_typavgwidth(wfunc->wintype, -1);
+                       }
+               }
+               else
+               {
+                       window_target = output_target;
+               }
+
+               path = (Path *)
+                       create_windowagg_path(root, window_rel, path, 
window_target,
+                                                                 
wflists->windowFuncs[wc->winref],
+                                                                 wc);
+       }
+
+       add_partial_path(window_rel, path);
+}
diff --git a/src/backend/optimizer/util/clauses.c 
b/src/backend/optimizer/util/clauses.c
index a48f2ed8433..1fd03a05e87 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -807,7 +807,13 @@ max_parallel_hazard_walker(Node *node, 
max_parallel_hazard_context *context)
         */
        else if (IsA(node, WindowFunc))
        {
-               if (max_parallel_hazard_test(PROPARALLEL_RESTRICTED, context))
+               /*
+                * In Cloudberry, we proess window fuctions by redistributeing 
the tuples
+                * if there is Partition By clause.
+                * Each partition is processed individually, whether in a 
single process
+                * or distributed parallel workers setup.
+                */
+               if (max_parallel_hazard_test(PROPARALLEL_SAFE, context))
                        return true;
        }
 
diff --git a/src/test/regress/expected/cluster.out 
b/src/test/regress/expected/cluster.out
index f62380f80f4..f68bb39a620 100644
--- a/src/test/regress/expected/cluster.out
+++ b/src/test/regress/expected/cluster.out
@@ -467,9 +467,9 @@ set enable_indexscan = off;
 set maintenance_work_mem = '1MB';
 cluster clstr_4 using cluster_sort;
 select * from
-(select hundred, lag(hundred) over () as lhundred,
-        thousand, lag(thousand) over () as lthousand,
-        tenthous, lag(tenthous) over () as ltenthous from clstr_4) ss
+(select hundred, lag(hundred) over (order by hundred) as lhundred,
+        thousand, lag(thousand) over (order by hundred) as lthousand,
+        tenthous, lag(tenthous) over (order by hundred) as ltenthous from 
clstr_4) ss
 where row(hundred, thousand, tenthous) <= row(lhundred, lthousand, ltenthous);
  hundred | lhundred | thousand | lthousand | tenthous | ltenthous 
 ---------+----------+----------+-----------+----------+-----------
diff --git a/src/test/regress/expected/select_parallel.out 
b/src/test/regress/expected/select_parallel.out
index eb36bb11f88..4de01f4f632 100644
--- a/src/test/regress/expected/select_parallel.out
+++ b/src/test/regress/expected/select_parallel.out
@@ -1056,6 +1056,7 @@ select count(*) from tenk1;
 reset force_parallel_mode;
 reset role;
 -- Window function calculation can't be pushed to workers.
+-- CBDB_PARALLEL: window function's subpath could be parallel.
 explain (costs off, verbose)
   select count(*) from tenk1 a where (unique1, two) in
     (select unique1, row_number() over() from tenk1 b);
@@ -1063,28 +1064,29 @@ explain (costs off, verbose)
 
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  Finalize Aggregate
    Output: count(*)
-   ->  Gather Motion 3:1  (slice1; segments: 3)
+   ->  Gather Motion 6:1  (slice1; segments: 6)
          Output: (PARTIAL count(*))
          ->  Partial Aggregate
                Output: PARTIAL count(*)
-               ->  Hash Semi Join
+               ->  Parallel Hash Semi Join
                      Hash Cond: ((a.unique1 = b.unique1) AND (a.two = 
(row_number() OVER (?))))
-                     ->  Seq Scan on public.tenk1 a
+                     ->  Parallel Seq Scan on public.tenk1 a
                            Output: a.unique1, a.unique2, a.two, a.four, a.ten, 
a.twenty, a.hundred, a.thousand, a.twothousand, a.fivethous, a.tenthous, a.odd, 
a.even, a.stringu1, a.stringu2, a.string4
-                     ->  Hash
+                     ->  Parallel Hash
                            Output: b.unique1, (row_number() OVER (?))
-                           ->  Redistribute Motion 1:3  (slice2; segments: 1)
+                           ->  Redistribute Motion 1:6  (slice2; segments: 1)
                                  Output: b.unique1, (row_number() OVER (?))
                                  Hash Key: b.unique1
+                                 Hash Module: 3
                                  ->  WindowAgg
                                        Output: b.unique1, row_number() OVER (?)
-                                       ->  Gather Motion 3:1  (slice3; 
segments: 3)
+                                       ->  Gather Motion 6:1  (slice3; 
segments: 6)
                                              Output: b.unique1
-                                             ->  Seq Scan on public.tenk1 b
+                                             ->  Parallel Seq Scan on 
public.tenk1 b
                                                    Output: b.unique1
  Settings: enable_parallel = 'on', min_parallel_table_scan_size = '0', 
optimizer = 'off', parallel_setup_cost = '0', parallel_tuple_cost = '0'
  Optimizer: Postgres query optimizer
-(23 rows)
+(24 rows)
 
 -- LIMIT/OFFSET within sub-selects can't be pushed to workers.
 explain (costs off)
diff --git a/src/test/regress/expected/statement_mem_for_windowagg.out 
b/src/test/regress/expected/statement_mem_for_windowagg.out
index d41610f6a30..fd1d066b7bd 100644
--- a/src/test/regress/expected/statement_mem_for_windowagg.out
+++ b/src/test/regress/expected/statement_mem_for_windowagg.out
@@ -2,6 +2,7 @@ CREATE TABLE dummy_table(x int, y int) DISTRIBUTED BY (y);
 INSERT INTO dummy_table SELECT generate_series(0, 20000), 0;
 INSERT INTO dummy_table SELECT generate_series(0, 20000), 3;
 INSERT INTO dummy_table SELECT generate_series(0, 20000), 10;
+set enable_parallel = off; 
 -- 1. Test that if we set statement_mem to a larger value, the tuplestore
 -- for caching the tuples in partition used in WindowAgg is able to be fitted
 -- in memory.
@@ -172,5 +173,6 @@ SELECT 
gp_inject_fault_infinite('distinct_winagg_perform_sort', 'reset', dbid)
 (3 rows)
 
 -- Do some clean-ups.
+reset enable_parallel;
 DROP TABLE dummy_table;
 RESET statement_mem;
diff --git a/src/test/regress/expected/window.out 
b/src/test/regress/expected/window.out
index 27b2a1aaf80..36ea794ff8a 100644
--- a/src/test/regress/expected/window.out
+++ b/src/test/regress/expected/window.out
@@ -1276,259 +1276,259 @@ FROM tenk1 WHERE unique1 < 10;
 (10 rows)
 
 set search_path=singleseg, public;
-SELECT sum(unique1) over (rows between current row and unbounded following),
+SELECT sum(unique1) over (order by unique1 rows between current row and 
unbounded following),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-  45 |       4 |    0
-  41 |       2 |    2
-  39 |       1 |    1
-  38 |       6 |    2
-  32 |       9 |    1
-  23 |       8 |    0
-  15 |       5 |    1
-  10 |       3 |    3
-   7 |       7 |    3
-   0 |       0 |    0
+  45 |       0 |    0
+  45 |       1 |    1
+  44 |       2 |    2
+  42 |       3 |    3
+  39 |       4 |    0
+  35 |       5 |    1
+  30 |       6 |    2
+  24 |       7 |    3
+  17 |       8 |    0
+   9 |       9 |    1
 (10 rows)
 
-SELECT sum(unique1) over (rows between 2 preceding and 2 following),
+SELECT sum(unique1) over (order by unique1 rows between 2 preceding and 2 
following),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-   7 |       4 |    0
-  13 |       2 |    2
-  22 |       1 |    1
-  26 |       6 |    2
-  29 |       9 |    1
-  31 |       8 |    0
-  32 |       5 |    1
-  23 |       3 |    3
-  15 |       7 |    3
-  10 |       0 |    0
+   3 |       0 |    0
+   6 |       1 |    1
+  10 |       2 |    2
+  15 |       3 |    3
+  20 |       4 |    0
+  25 |       5 |    1
+  30 |       6 |    2
+  35 |       7 |    3
+  30 |       8 |    0
+  24 |       9 |    1
 (10 rows)
 
-SELECT sum(unique1) over (rows between 2 preceding and 2 following exclude no 
others),
+SELECT sum(unique1) over (order by unique1 rows between 2 preceding and 2 
following exclude no others),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-   7 |       4 |    0
-  13 |       2 |    2
-  22 |       1 |    1
-  26 |       6 |    2
-  29 |       9 |    1
-  31 |       8 |    0
-  32 |       5 |    1
-  23 |       3 |    3
-  15 |       7 |    3
-  10 |       0 |    0
+   3 |       0 |    0
+   6 |       1 |    1
+  10 |       2 |    2
+  15 |       3 |    3
+  20 |       4 |    0
+  25 |       5 |    1
+  30 |       6 |    2
+  35 |       7 |    3
+  30 |       8 |    0
+  24 |       9 |    1
 (10 rows)
 
-SELECT sum(unique1) over (rows between 2 preceding and 2 following exclude 
current row),
+SELECT sum(unique1) over (order by unique1 rows between 2 preceding and 2 
following exclude current row),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-   3 |       4 |    0
-  11 |       2 |    2
-  21 |       1 |    1
-  20 |       6 |    2
-  20 |       9 |    1
-  23 |       8 |    0
-  27 |       5 |    1
-  20 |       3 |    3
-   8 |       7 |    3
-  10 |       0 |    0
+   3 |       0 |    0
+   5 |       1 |    1
+   8 |       2 |    2
+  12 |       3 |    3
+  16 |       4 |    0
+  20 |       5 |    1
+  24 |       6 |    2
+  28 |       7 |    3
+  22 |       8 |    0
+  15 |       9 |    1
 (10 rows)
 
-SELECT sum(unique1) over (rows between 2 preceding and 2 following exclude 
group),
+SELECT sum(unique1) over (order by unique1 rows between 2 preceding and 2 
following exclude group),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-     |       4 |    0
-     |       2 |    2
-     |       1 |    1
-     |       6 |    2
-     |       9 |    1
-     |       8 |    0
-     |       5 |    1
-     |       3 |    3
-     |       7 |    3
-     |       0 |    0
+   3 |       0 |    0
+   5 |       1 |    1
+   8 |       2 |    2
+  12 |       3 |    3
+  16 |       4 |    0
+  20 |       5 |    1
+  24 |       6 |    2
+  28 |       7 |    3
+  22 |       8 |    0
+  15 |       9 |    1
 (10 rows)
 
-SELECT sum(unique1) over (rows between 2 preceding and 2 following exclude 
ties),
+SELECT sum(unique1) over (order by unique1 rows between 2 preceding and 2 
following exclude ties),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-   4 |       4 |    0
-   2 |       2 |    2
-   1 |       1 |    1
-   6 |       6 |    2
-   9 |       9 |    1
-   8 |       8 |    0
-   5 |       5 |    1
-   3 |       3 |    3
-   7 |       7 |    3
-   0 |       0 |    0
+   3 |       0 |    0
+   6 |       1 |    1
+  10 |       2 |    2
+  15 |       3 |    3
+  20 |       4 |    0
+  25 |       5 |    1
+  30 |       6 |    2
+  35 |       7 |    3
+  30 |       8 |    0
+  24 |       9 |    1
 (10 rows)
 
-SELECT first_value(unique1) over (ORDER BY four rows between current row and 2 
following exclude current row),
+SELECT first_value(unique1) over (ORDER BY four, unique1 rows between current 
row and 2 following exclude current row),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
  first_value | unique1 | four 
 -------------+---------+------
-           8 |       0 |    0
-           4 |       8 |    0
-           5 |       4 |    0
+           4 |       0 |    0
+           8 |       4 |    0
+           1 |       8 |    0
+           5 |       1 |    1
            9 |       5 |    1
-           1 |       9 |    1
-           6 |       1 |    1
-           2 |       6 |    2
-           3 |       2 |    2
+           2 |       9 |    1
+           6 |       2 |    2
+           3 |       6 |    2
            7 |       3 |    3
              |       7 |    3
 (10 rows)
 
-SELECT first_value(unique1) over (ORDER BY four rows between current row and 2 
following exclude group),
+SELECT first_value(unique1) over (ORDER BY four, unique1 rows between current 
row and 2 following exclude group),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
  first_value | unique1 | four 
 -------------+---------+------
-             |       0 |    0
-           5 |       8 |    0
-           5 |       4 |    0
-             |       5 |    1
-           6 |       9 |    1
-           6 |       1 |    1
+           4 |       0 |    0
+           8 |       4 |    0
+           1 |       8 |    0
+           5 |       1 |    1
+           9 |       5 |    1
+           2 |       9 |    1
+           6 |       2 |    2
            3 |       6 |    2
-           3 |       2 |    2
-             |       3 |    3
+           7 |       3 |    3
              |       7 |    3
 (10 rows)
 
-SELECT first_value(unique1) over (ORDER BY four rows between current row and 2 
following exclude ties),
+SELECT first_value(unique1) over (ORDER BY four, unique1 rows between current 
row and 2 following exclude ties),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
  first_value | unique1 | four 
 -------------+---------+------
            0 |       0 |    0
-           8 |       8 |    0
            4 |       4 |    0
+           8 |       8 |    0
+           1 |       1 |    1
            5 |       5 |    1
            9 |       9 |    1
-           1 |       1 |    1
-           6 |       6 |    2
            2 |       2 |    2
+           6 |       6 |    2
            3 |       3 |    3
            7 |       7 |    3
 (10 rows)
 
-SELECT last_value(unique1) over (ORDER BY four rows between current row and 2 
following exclude current row),
+SELECT last_value(unique1) over (ORDER BY four, unique1 rows between current 
row and 2 following exclude current row),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
  last_value | unique1 | four 
 ------------+---------+------
-          4 |       0 |    0
+          8 |       0 |    0
+          1 |       4 |    0
           5 |       8 |    0
-          9 |       4 |    0
-          1 |       5 |    1
+          9 |       1 |    1
+          2 |       5 |    1
           6 |       9 |    1
-          2 |       1 |    1
-          3 |       6 |    2
-          7 |       2 |    2
+          3 |       2 |    2
+          7 |       6 |    2
           7 |       3 |    3
             |       7 |    3
 (10 rows)
 
-SELECT last_value(unique1) over (ORDER BY four rows between current row and 2 
following exclude group),
+SELECT last_value(unique1) over (ORDER BY four, unique1 rows between current 
row and 2 following exclude group),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
  last_value | unique1 | four 
 ------------+---------+------
-            |       0 |    0
+          8 |       0 |    0
+          1 |       4 |    0
           5 |       8 |    0
-          9 |       4 |    0
-            |       5 |    1
+          9 |       1 |    1
+          2 |       5 |    1
           6 |       9 |    1
-          2 |       1 |    1
-          3 |       6 |    2
-          7 |       2 |    2
-            |       3 |    3
+          3 |       2 |    2
+          7 |       6 |    2
+          7 |       3 |    3
             |       7 |    3
 (10 rows)
 
-SELECT last_value(unique1) over (ORDER BY four rows between current row and 2 
following exclude ties),
+SELECT last_value(unique1) over (ORDER BY four, unique1 rows between current 
row and 2 following exclude ties),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
  last_value | unique1 | four 
 ------------+---------+------
-          0 |       0 |    0
+          8 |       0 |    0
+          1 |       4 |    0
           5 |       8 |    0
-          9 |       4 |    0
-          5 |       5 |    1
+          9 |       1 |    1
+          2 |       5 |    1
           6 |       9 |    1
-          2 |       1 |    1
-          3 |       6 |    2
-          7 |       2 |    2
-          3 |       3 |    3
+          3 |       2 |    2
+          7 |       6 |    2
+          7 |       3 |    3
           7 |       7 |    3
 (10 rows)
 
-SELECT sum(unique1) over (rows between 2 preceding and 1 preceding),
+SELECT sum(unique1) over (order by unique1 rows between 2 preceding and 1 
preceding),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-     |       4 |    0
-   4 |       2 |    2
-   6 |       1 |    1
-   3 |       6 |    2
-   7 |       9 |    1
-  15 |       8 |    0
-  17 |       5 |    1
-  13 |       3 |    3
-   8 |       7 |    3
-  10 |       0 |    0
+     |       0 |    0
+   0 |       1 |    1
+   1 |       2 |    2
+   3 |       3 |    3
+   5 |       4 |    0
+   7 |       5 |    1
+   9 |       6 |    2
+  11 |       7 |    3
+  13 |       8 |    0
+  15 |       9 |    1
 (10 rows)
 
-SELECT sum(unique1) over (rows between 1 following and 3 following),
+SELECT sum(unique1) over (order by unique1 rows between 1 following and 3 
following),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-   9 |       4 |    0
-  16 |       2 |    2
-  23 |       1 |    1
-  22 |       6 |    2
-  16 |       9 |    1
-  15 |       8 |    0
-  10 |       5 |    1
-   7 |       3 |    3
-   0 |       7 |    3
-     |       0 |    0
+   6 |       0 |    0
+   9 |       1 |    1
+  12 |       2 |    2
+  15 |       3 |    3
+  18 |       4 |    0
+  21 |       5 |    1
+  24 |       6 |    2
+  17 |       7 |    3
+   9 |       8 |    0
+     |       9 |    1
 (10 rows)
 
-SELECT sum(unique1) over (rows between unbounded preceding and 1 following),
+SELECT sum(unique1) over (order by unique1 rows between unbounded preceding 
and 1 following),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-   6 |       4 |    0
-   7 |       2 |    2
-  13 |       1 |    1
-  22 |       6 |    2
-  30 |       9 |    1
-  35 |       8 |    0
-  38 |       5 |    1
-  45 |       3 |    3
-  45 |       7 |    3
-  45 |       0 |    0
+   1 |       0 |    0
+   3 |       1 |    1
+   6 |       2 |    2
+  10 |       3 |    3
+  15 |       4 |    0
+  21 |       5 |    1
+  28 |       6 |    2
+  36 |       7 |    3
+  45 |       8 |    0
+  45 |       9 |    1
 (10 rows)
 
 SELECT sum(unique1) over (w range between current row and unbounded following),
@@ -1603,19 +1603,19 @@ SELECT first_value(unique1) over w,
        nth_value(unique1, 2) over w AS nth_2,
        last_value(unique1) over w, unique1, four
 FROM tenk1 WHERE unique1 < 10
-WINDOW w AS (order by four range between current row and unbounded following);
+WINDOW w AS (order by unique1, four range between current row and unbounded 
following);
  first_value | nth_2 | last_value | unique1 | four 
 -------------+-------+------------+---------+------
-           0 |     8 |          7 |       0 |    0
-           0 |     8 |          7 |       8 |    0
-           0 |     8 |          7 |       4 |    0
-           5 |     9 |          7 |       5 |    1
-           5 |     9 |          7 |       9 |    1
-           5 |     9 |          7 |       1 |    1
-           6 |     2 |          7 |       6 |    2
-           6 |     2 |          7 |       2 |    2
-           3 |     7 |          7 |       3 |    3
-           3 |     7 |          7 |       7 |    3
+           0 |     1 |          9 |       0 |    0
+           1 |     2 |          9 |       1 |    1
+           2 |     3 |          9 |       2 |    2
+           3 |     4 |          9 |       3 |    3
+           4 |     5 |          9 |       4 |    0
+           5 |     6 |          9 |       5 |    1
+           6 |     7 |          9 |       6 |    2
+           7 |     8 |          9 |       7 |    3
+           8 |     9 |          9 |       8 |    0
+           9 |       |          9 |       9 |    1
 (10 rows)
 
 SELECT sum(unique1) over
diff --git a/src/test/regress/expected/window_optimizer.out 
b/src/test/regress/expected/window_optimizer.out
index f6bdcc3b6c7..8576209f725 100644
--- a/src/test/regress/expected/window_optimizer.out
+++ b/src/test/regress/expected/window_optimizer.out
@@ -16,6 +16,8 @@ CREATE TEMPORARY TABLE empsalary (
     salary int,
     enroll_date date
 );
+NOTICE:  Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 
'depname' as the Apache Cloudberry data distribution key for this table.
+HINT:  The 'DISTRIBUTED BY' clause determines the distribution of data. Make 
sure column(s) chosen are the optimal data distribution key to minimize skew.
 INSERT INTO empsalary VALUES
 ('develop', 10, 5200, '2007-08-01'),
 ('sales', 1, 5000, '2006-10-01'),
@@ -87,30 +89,30 @@ GROUP BY four, ten ORDER BY four, ten;
 SELECT depname, empno, salary, sum(salary) OVER w FROM empsalary WINDOW w AS 
(PARTITION BY depname);
   depname  | empno | salary |  sum  
 -----------+-------+--------+-------
+ develop   |    11 |   5200 | 25100
+ develop   |     7 |   4200 | 25100
+ develop   |     9 |   4500 | 25100
+ develop   |     8 |   6000 | 25100
+ develop   |    10 |   5200 | 25100
  personnel |     5 |   3500 |  7400
  personnel |     2 |   3900 |  7400
+ sales     |     3 |   4800 | 14600
  sales     |     1 |   5000 | 14600
  sales     |     4 |   4800 | 14600
- sales     |     3 |   4800 | 14600
- develop   |    10 |   5200 | 25100
- develop   |     7 |   4200 | 25100
- develop   |     9 |   4500 | 25100
- develop   |     8 |   6000 | 25100
- develop   |    11 |   5200 | 25100
 (10 rows)
 
 SELECT depname, empno, salary, rank() OVER w FROM empsalary WINDOW w AS 
(PARTITION BY depname ORDER BY salary) ORDER BY rank() OVER w;
   depname  | empno | salary | rank 
 -----------+-------+--------+------
  develop   |     7 |   4200 |    1
- sales     |     4 |   4800 |    1
- sales     |     3 |   4800 |    1
  personnel |     5 |   3500 |    1
+ sales     |     3 |   4800 |    1
+ sales     |     4 |   4800 |    1
  personnel |     2 |   3900 |    2
  develop   |     9 |   4500 |    2
- develop   |    10 |   5200 |    3
- develop   |    11 |   5200 |    3
  sales     |     1 |   5000 |    3
+ develop   |    11 |   5200 |    3
+ develop   |    10 |   5200 |    3
  develop   |     8 |   6000 |    5
 (10 rows)
 
@@ -155,16 +157,16 @@ SELECT four FROM tenk1 WHERE FALSE WINDOW w AS (PARTITION 
BY ten);
 SELECT sum(four) OVER (PARTITION BY ten ORDER BY unique2) AS sum_1, ten, four 
FROM tenk1 WHERE unique2 < 10;
  sum_1 | ten | four 
 -------+-----+------
-     1 |   9 |    1
+     3 |   3 |    3
+     0 |   4 |    0
+     1 |   7 |    1
      0 |   0 |    0
      0 |   0 |    0
      2 |   0 |    2
      3 |   1 |    3
      4 |   1 |    1
      5 |   1 |    1
-     3 |   3 |    3
-     0 |   4 |    0
-     1 |   7 |    1
+     1 |   9 |    1
 (10 rows)
 
 SELECT row_number() OVER (ORDER BY unique2) FROM tenk1 WHERE unique2 < 10;
@@ -185,6 +187,9 @@ SELECT row_number() OVER (ORDER BY unique2) FROM tenk1 
WHERE unique2 < 10;
 SELECT rank() OVER (PARTITION BY four ORDER BY ten) AS rank_1, ten, four FROM 
tenk1 WHERE unique2 < 10;
  rank_1 | ten | four 
 --------+-----+------
+      1 |   0 |    2
+      1 |   1 |    3
+      2 |   3 |    3
       1 |   0 |    0
       1 |   0 |    0
       3 |   4 |    0
@@ -192,14 +197,12 @@ SELECT rank() OVER (PARTITION BY four ORDER BY ten) AS 
rank_1, ten, four FROM te
       1 |   1 |    1
       3 |   7 |    1
       4 |   9 |    1
-      1 |   0 |    2
-      1 |   1 |    3
-      2 |   3 |    3
 (10 rows)
 
 SELECT dense_rank() OVER (PARTITION BY four ORDER BY ten), ten, four FROM 
tenk1 WHERE unique2 < 10;
  dense_rank | ten | four 
 ------------+-----+------
+          1 |   0 |    2
           1 |   1 |    3
           2 |   3 |    3
           1 |   0 |    0
@@ -209,7 +212,6 @@ SELECT dense_rank() OVER (PARTITION BY four ORDER BY ten), 
ten, four FROM tenk1
           1 |   1 |    1
           2 |   7 |    1
           3 |   9 |    1
-          1 |   0 |    2
 (10 rows)
 
 SELECT percent_rank() OVER (PARTITION BY four ORDER BY ten), ten, four FROM 
tenk1 WHERE unique2 < 10;
@@ -267,6 +269,7 @@ SELECT ntile(NULL) OVER (ORDER BY ten, four), ten, four 
FROM tenk1 LIMIT 2;
 SELECT lag(ten) OVER (PARTITION BY four ORDER BY ten), ten, four FROM tenk1 
WHERE unique2 < 10;
  lag | ten | four 
 -----+-----+------
+     |   0 |    2
      |   1 |    3
    1 |   3 |    3
      |   0 |    0
@@ -276,12 +279,12 @@ SELECT lag(ten) OVER (PARTITION BY four ORDER BY ten), 
ten, four FROM tenk1 WHER
    1 |   1 |    1
    1 |   7 |    1
    7 |   9 |    1
-     |   0 |    2
 (10 rows)
 
 SELECT lag(ten, four) OVER (PARTITION BY four ORDER BY ten), ten, four FROM 
tenk1 WHERE unique2 < 10;
  lag | ten | four 
 -----+-----+------
+     |   0 |    2
      |   1 |    3
      |   3 |    3
    0 |   0 |    0
@@ -291,12 +294,14 @@ SELECT lag(ten, four) OVER (PARTITION BY four ORDER BY 
ten), ten, four FROM tenk
    1 |   1 |    1
    1 |   7 |    1
    7 |   9 |    1
-     |   0 |    2
 (10 rows)
 
 SELECT lag(ten, four, 0) OVER (PARTITION BY four ORDER BY ten), ten, four FROM 
tenk1 WHERE unique2 < 10;
  lag | ten | four 
 -----+-----+------
+   0 |   0 |    2
+   0 |   1 |    3
+   0 |   3 |    3
    0 |   0 |    0
    0 |   0 |    0
    4 |   4 |    0
@@ -304,9 +309,6 @@ SELECT lag(ten, four, 0) OVER (PARTITION BY four ORDER BY 
ten), ten, four FROM t
    1 |   1 |    1
    1 |   7 |    1
    7 |   9 |    1
-   0 |   0 |    2
-   0 |   1 |    3
-   0 |   3 |    3
 (10 rows)
 
 SELECT lag(ten, four, 0.7) OVER (PARTITION BY four ORDER BY ten), ten, four 
FROM tenk1 WHERE unique2 < 10 ORDER BY four, ten;
@@ -327,6 +329,7 @@ SELECT lag(ten, four, 0.7) OVER (PARTITION BY four ORDER BY 
ten), ten, four FROM
 SELECT lead(ten) OVER (PARTITION BY four ORDER BY ten), ten, four FROM tenk1 
WHERE unique2 < 10;
  lead | ten | four 
 ------+-----+------
+      |   0 |    2
     3 |   1 |    3
       |   3 |    3
     0 |   0 |    0
@@ -336,12 +339,12 @@ SELECT lead(ten) OVER (PARTITION BY four ORDER BY ten), 
ten, four FROM tenk1 WHE
     7 |   1 |    1
     9 |   7 |    1
       |   9 |    1
-      |   0 |    2
 (10 rows)
 
 SELECT lead(ten * 2, 1) OVER (PARTITION BY four ORDER BY ten), ten, four FROM 
tenk1 WHERE unique2 < 10;
  lead | ten | four 
 ------+-----+------
+      |   0 |    2
     6 |   1 |    3
       |   3 |    3
     0 |   0 |    0
@@ -351,12 +354,12 @@ SELECT lead(ten * 2, 1) OVER (PARTITION BY four ORDER BY 
ten), ten, four FROM te
    14 |   1 |    1
    18 |   7 |    1
       |   9 |    1
-      |   0 |    2
 (10 rows)
 
 SELECT lead(ten * 2, 1, -1) OVER (PARTITION BY four ORDER BY ten), ten, four 
FROM tenk1 WHERE unique2 < 10;
  lead | ten | four 
 ------+-----+------
+   -1 |   0 |    2
     6 |   1 |    3
    -1 |   3 |    3
     0 |   0 |    0
@@ -366,7 +369,6 @@ SELECT lead(ten * 2, 1, -1) OVER (PARTITION BY four ORDER 
BY ten), ten, four FRO
    14 |   1 |    1
    18 |   7 |    1
    -1 |   9 |    1
-   -1 |   0 |    2
 (10 rows)
 
 SELECT lead(ten * 2, 1, -1.4) OVER (PARTITION BY four ORDER BY ten), ten, four 
FROM tenk1 WHERE unique2 < 10 ORDER BY four, ten;
@@ -387,6 +389,7 @@ SELECT lead(ten * 2, 1, -1.4) OVER (PARTITION BY four ORDER 
BY ten), ten, four F
 SELECT first_value(ten) OVER (PARTITION BY four ORDER BY ten), ten, four FROM 
tenk1 WHERE unique2 < 10;
  first_value | ten | four 
 -------------+-----+------
+           0 |   0 |    2
            1 |   1 |    3
            1 |   3 |    3
            0 |   0 |    0
@@ -396,7 +399,6 @@ SELECT first_value(ten) OVER (PARTITION BY four ORDER BY 
ten), ten, four FROM te
            1 |   1 |    1
            1 |   7 |    1
            1 |   9 |    1
-           0 |   0 |    2
 (10 rows)
 
 -- test split window func
@@ -732,41 +734,41 @@ SELECT * FROM (SELECT rank() OVER (PARTITION BY four 
ORDER BY ten) AS rank_1, te
 SELECT * FROM (SELECT row_number() OVER (PARTITION BY four ORDER BY ten) AS 
rank_1, ten, four FROM tenk1 WHERE unique2 < 10) t WHERE rank_1 < 3;
  rank_1 | ten | four 
 --------+-----+------
-      1 |   0 |    2
-      1 |   1 |    3
-      2 |   3 |    3
       1 |   0 |    0
       2 |   0 |    0
       1 |   1 |    1
       2 |   1 |    1
+      1 |   0 |    2
+      1 |   1 |    3
+      2 |   3 |    3
 (7 rows)
 
 SELECT * FROM (SELECT dense_rank() OVER (PARTITION BY four ORDER BY ten) AS 
rank_1, ten, four FROM tenk1 WHERE unique2 < 10) t WHERE rank_1 < 3;
  rank_1 | ten | four 
 --------+-----+------
-      1 |   0 |    2
-      1 |   1 |    3
-      2 |   3 |    3
       1 |   0 |    0
       1 |   0 |    0
       2 |   4 |    0
       1 |   1 |    1
       1 |   1 |    1
       2 |   7 |    1
+      1 |   0 |    2
+      1 |   1 |    3
+      2 |   3 |    3
 (9 rows)
 
 SELECT * FROM (SELECT rank() OVER (PARTITION BY four ORDER BY ten) AS rank_1, 
ten, four FROM tenk1 WHERE unique2 < 10) t WHERE rank_1 <= 3;
  rank_1 | ten | four 
 --------+-----+------
+      1 |   0 |    2
+      1 |   1 |    3
+      2 |   3 |    3
       1 |   0 |    0
       1 |   0 |    0
       3 |   4 |    0
       1 |   1 |    1
       1 |   1 |    1
       3 |   7 |    1
-      1 |   0 |    2
-      1 |   1 |    3
-      2 |   3 |    3
 (9 rows)
 
 SELECT * FROM (SELECT row_number() OVER (PARTITION BY four ORDER BY ten) AS 
rank_1, ten, four FROM tenk1 WHERE unique2 < 10) t WHERE rank_1 <= 3;
@@ -814,27 +816,27 @@ SELECT * FROM (SELECT rank() OVER (PARTITION BY four 
ORDER BY ten) AS rank_1, te
 SELECT * FROM (SELECT row_number() OVER (PARTITION BY four ORDER BY ten) AS 
rank_1, ten, four FROM tenk1 WHERE unique2 < 10) t WHERE rank_1 < 3;
  rank_1 | ten | four 
 --------+-----+------
-      1 |   0 |    2
-      1 |   1 |    3
-      2 |   3 |    3
       1 |   0 |    0
       2 |   0 |    0
       1 |   1 |    1
       2 |   1 |    1
+      1 |   0 |    2
+      1 |   1 |    3
+      2 |   3 |    3
 (7 rows)
 
 SELECT * FROM (SELECT dense_rank() OVER (PARTITION BY four ORDER BY ten) AS 
rank_1, ten, four FROM tenk1 WHERE unique2 < 10) t WHERE rank_1 < 3;
  rank_1 | ten | four 
 --------+-----+------
-      1 |   0 |    2
-      1 |   1 |    3
-      2 |   3 |    3
       1 |   0 |    0
       1 |   0 |    0
       2 |   4 |    0
       1 |   1 |    1
       1 |   1 |    1
       2 |   7 |    1
+      1 |   0 |    2
+      1 |   1 |    3
+      2 |   3 |    3
 (9 rows)
 
 SELECT * FROM (SELECT rank() OVER (PARTITION BY four ORDER BY ten) AS rank_1, 
ten, four FROM tenk1 WHERE unique2 < 10) t WHERE rank_1 <= 3;
@@ -888,9 +890,9 @@ reset optimizer_force_split_window_function;
 SELECT last_value(ten) OVER (ORDER BY ten), ten, four FROM tenk1 WHERE unique2 
< 10;
  last_value | ten | four 
 ------------+-----+------
-          0 |   0 |    2
           0 |   0 |    0
           0 |   0 |    0
+          0 |   0 |    2
           1 |   1 |    1
           1 |   1 |    3
           1 |   1 |    1
@@ -967,6 +969,7 @@ SELECT (count(*) OVER (PARTITION BY four ORDER BY ten) +
   FROM tenk1 WHERE unique2 < 10;
  cntsum 
 --------
+ 51
  92
  136
  22
@@ -976,7 +979,6 @@ SELECT (count(*) OVER (PARTITION BY four ORDER BY ten) +
  24
  82
  92
- 51
 (10 rows)
 
 -- opexpr with different windows evaluation.
@@ -995,6 +997,9 @@ WHERE total <> fourcount + twosum;
 SELECT avg(four) OVER (PARTITION BY four ORDER BY thousand / 100) FROM tenk1 
WHERE unique2 < 10;
           avg           
 ------------------------
+     2.0000000000000000
+     3.0000000000000000
+     3.0000000000000000
  0.00000000000000000000
  0.00000000000000000000
  0.00000000000000000000
@@ -1002,9 +1007,6 @@ SELECT avg(four) OVER (PARTITION BY four ORDER BY 
thousand / 100) FROM tenk1 WHE
  1.00000000000000000000
  1.00000000000000000000
  1.00000000000000000000
-     3.0000000000000000
-     3.0000000000000000
-     2.0000000000000000
 (10 rows)
 
 SELECT ten, two, sum(hundred) AS gsum, sum(sum(hundred)) OVER win AS wsum
@@ -1030,9 +1032,9 @@ SELECT sum(salary),
 FROM empsalary GROUP BY depname;
   sum  | row_number |  sum  
 -------+------------+-------
- 25100 |          1 | 47100
-  7400 |          2 | 22000
  14600 |          3 | 14600
+  7400 |          2 | 22000
+ 25100 |          1 | 47100
 (3 rows)
 
 -- identical windows with different names
@@ -1057,8 +1059,6 @@ SELECT lead(ten, (SELECT two FROM tenk1 WHERE s.unique2 = 
unique2)) OVER (PARTIT
 FROM tenk1 s WHERE unique2 < 10;
  lead 
 ------
-    3
-     
     0
     0
     4
@@ -1067,6 +1067,8 @@ FROM tenk1 s WHERE unique2 < 10;
     9
      
     0
+    3
+     
 (10 rows)
 
 -- empty table
@@ -1156,7 +1158,7 @@ select first_value(max(x)) over (), y
                      ->  Streaming Partial HashAggregate
                            Group Key: (ten + four)
                            ->  Seq Scan on tenk1
- Optimizer: Pivotal Optimizer (GPORCA) version 3.83.0
+ Optimizer: GPORCA
 (10 rows)
 
 -- test non-default frame specifications
@@ -1166,6 +1168,11 @@ SELECT four, ten,
 FROM (select distinct ten, four from tenk1) ss;
  four | ten | sum | last_value 
 ------+-----+-----+------------
+    2 |   0 |   0 |          0
+    2 |   2 |   2 |          2
+    2 |   4 |   6 |          4
+    2 |   6 |  12 |          6
+    2 |   8 |  20 |          8
     3 |   1 |   1 |          1
     3 |   3 |   4 |          3
     3 |   5 |   9 |          5
@@ -1181,11 +1188,6 @@ FROM (select distinct ten, four from tenk1) ss;
     1 |   5 |   9 |          5
     1 |   7 |  16 |          7
     1 |   9 |  25 |          9
-    2 |   0 |   0 |          0
-    2 |   2 |   2 |          2
-    2 |   4 |   6 |          4
-    2 |   6 |  12 |          6
-    2 |   8 |  20 |          8
 (20 rows)
 
 SELECT four, ten,
@@ -1194,16 +1196,6 @@ SELECT four, ten,
 FROM (select distinct ten, four from tenk1) ss;
  four | ten | sum | last_value 
 ------+-----+-----+------------
-    0 |   0 |   0 |          0
-    0 |   2 |   2 |          2
-    0 |   4 |   6 |          4
-    0 |   6 |  12 |          6
-    0 |   8 |  20 |          8
-    1 |   1 |   1 |          1
-    1 |   3 |   4 |          3
-    1 |   5 |   9 |          5
-    1 |   7 |  16 |          7
-    1 |   9 |  25 |          9
     2 |   0 |   0 |          0
     2 |   2 |   2 |          2
     2 |   4 |   6 |          4
@@ -1214,6 +1206,16 @@ FROM (select distinct ten, four from tenk1) ss;
     3 |   5 |   9 |          5
     3 |   7 |  16 |          7
     3 |   9 |  25 |          9
+    0 |   0 |   0 |          0
+    0 |   2 |   2 |          2
+    0 |   4 |   6 |          4
+    0 |   6 |  12 |          6
+    0 |   8 |  20 |          8
+    1 |   1 |   1 |          1
+    1 |   3 |   4 |          3
+    1 |   5 |   9 |          5
+    1 |   7 |  16 |          7
+    1 |   9 |  25 |          9
 (20 rows)
 
 SELECT four, ten,
@@ -1222,6 +1224,11 @@ SELECT four, ten,
 FROM (select distinct ten, four from tenk1) ss;
  four | ten | sum | last_value 
 ------+-----+-----+------------
+    2 |   0 |  20 |          8
+    2 |   2 |  20 |          8
+    2 |   4 |  20 |          8
+    2 |   6 |  20 |          8
+    2 |   8 |  20 |          8
     3 |   1 |  25 |          9
     3 |   3 |  25 |          9
     3 |   5 |  25 |          9
@@ -1237,11 +1244,6 @@ FROM (select distinct ten, four from tenk1) ss;
     1 |   5 |  25 |          9
     1 |   7 |  25 |          9
     1 |   9 |  25 |          9
-    2 |   0 |  20 |          8
-    2 |   2 |  20 |          8
-    2 |   4 |  20 |          8
-    2 |   6 |  20 |          8
-    2 |   8 |  20 |          8
 (20 rows)
 
 SELECT four, ten/4 as two,
@@ -1250,6 +1252,11 @@ SELECT four, ten/4 as two,
 FROM (select distinct ten, four from tenk1) ss;
  four | two | sum | last_value 
 ------+-----+-----+------------
+    2 |   0 |   0 |          0
+    2 |   0 |   0 |          0
+    2 |   1 |   2 |          1
+    2 |   1 |   2 |          1
+    2 |   2 |   4 |          2
     3 |   0 |   0 |          0
     3 |   0 |   0 |          0
     3 |   1 |   2 |          1
@@ -1265,11 +1272,6 @@ FROM (select distinct ten, four from tenk1) ss;
     1 |   1 |   2 |          1
     1 |   1 |   2 |          1
     1 |   2 |   4 |          2
-    2 |   0 |   0 |          0
-    2 |   0 |   0 |          0
-    2 |   1 |   2 |          1
-    2 |   1 |   2 |          1
-    2 |   2 |   4 |          2
 (20 rows)
 
 SELECT four, ten/4 as two,
@@ -1278,6 +1280,11 @@ SELECT four, ten/4 as two,
 FROM (select distinct ten, four from tenk1) ss;
  four | two | sum | last_value 
 ------+-----+-----+------------
+    2 |   0 |   0 |          0
+    2 |   0 |   0 |          0
+    2 |   1 |   1 |          1
+    2 |   1 |   2 |          1
+    2 |   2 |   4 |          2
     3 |   0 |   0 |          0
     3 |   0 |   0 |          0
     3 |   1 |   1 |          1
@@ -1293,11 +1300,6 @@ FROM (select distinct ten, four from tenk1) ss;
     1 |   1 |   1 |          1
     1 |   1 |   2 |          1
     1 |   2 |   4 |          2
-    2 |   0 |   0 |          0
-    2 |   0 |   0 |          0
-    2 |   1 |   1 |          1
-    2 |   1 |   2 |          1
-    2 |   2 |   4 |          2
 (20 rows)
 
 SELECT sum(unique1) over (order by four range between current row and 
unbounded following),
@@ -1305,272 +1307,272 @@ SELECT sum(unique1) over (order by four range between 
current row and unbounded
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-  45 |       0 |    0
-  45 |       8 |    0
   45 |       4 |    0
-  33 |       5 |    1
+  45 |       8 |    0
+  45 |       0 |    0
   33 |       1 |    1
+  33 |       5 |    1
   33 |       9 |    1
-  18 |       2 |    2
   18 |       6 |    2
-  10 |       7 |    3
+  18 |       2 |    2
   10 |       3 |    3
+  10 |       7 |    3
 (10 rows)
 
 set search_path=singleseg, public;
-SELECT sum(unique1) over (rows between current row and unbounded following),
+SELECT sum(unique1) over (order by unique1 rows between current row and 
unbounded following),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-  45 |       4 |    0
-  41 |       2 |    2
-  39 |       1 |    1
-  38 |       6 |    2
-  32 |       9 |    1
-  23 |       8 |    0
-  15 |       5 |    1
-  10 |       3 |    3
-   7 |       7 |    3
-   0 |       0 |    0
+  45 |       0 |    0
+  45 |       1 |    1
+  44 |       2 |    2
+  42 |       3 |    3
+  39 |       4 |    0
+  35 |       5 |    1
+  30 |       6 |    2
+  24 |       7 |    3
+  17 |       8 |    0
+   9 |       9 |    1
 (10 rows)
 
-SELECT sum(unique1) over (rows between 2 preceding and 2 following),
+SELECT sum(unique1) over (order by unique1 rows between 2 preceding and 2 
following),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-   7 |       4 |    0
-  13 |       2 |    2
-  22 |       1 |    1
-  26 |       6 |    2
-  29 |       9 |    1
-  31 |       8 |    0
-  32 |       5 |    1
-  23 |       3 |    3
-  15 |       7 |    3
-  10 |       0 |    0
+   3 |       0 |    0
+   6 |       1 |    1
+  10 |       2 |    2
+  15 |       3 |    3
+  20 |       4 |    0
+  25 |       5 |    1
+  30 |       6 |    2
+  35 |       7 |    3
+  30 |       8 |    0
+  24 |       9 |    1
 (10 rows)
 
-SELECT sum(unique1) over (rows between 2 preceding and 2 following exclude no 
others),
+SELECT sum(unique1) over (order by unique1 rows between 2 preceding and 2 
following exclude no others),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-   7 |       4 |    0
-  13 |       2 |    2
-  22 |       1 |    1
-  26 |       6 |    2
-  29 |       9 |    1
-  31 |       8 |    0
-  32 |       5 |    1
-  23 |       3 |    3
-  15 |       7 |    3
-  10 |       0 |    0
+   3 |       0 |    0
+   6 |       1 |    1
+  10 |       2 |    2
+  15 |       3 |    3
+  20 |       4 |    0
+  25 |       5 |    1
+  30 |       6 |    2
+  35 |       7 |    3
+  30 |       8 |    0
+  24 |       9 |    1
 (10 rows)
 
-SELECT sum(unique1) over (rows between 2 preceding and 2 following exclude 
current row),
+SELECT sum(unique1) over (order by unique1 rows between 2 preceding and 2 
following exclude current row),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-   3 |       4 |    0
-  11 |       2 |    2
-  21 |       1 |    1
-  20 |       6 |    2
-  20 |       9 |    1
-  23 |       8 |    0
-  27 |       5 |    1
-  20 |       3 |    3
-   8 |       7 |    3
-  10 |       0 |    0
+   3 |       0 |    0
+   5 |       1 |    1
+   8 |       2 |    2
+  12 |       3 |    3
+  16 |       4 |    0
+  20 |       5 |    1
+  24 |       6 |    2
+  28 |       7 |    3
+  22 |       8 |    0
+  15 |       9 |    1
 (10 rows)
 
-SELECT sum(unique1) over (rows between 2 preceding and 2 following exclude 
group),
+SELECT sum(unique1) over (order by unique1 rows between 2 preceding and 2 
following exclude group),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-     |       4 |    0
-     |       2 |    2
-     |       1 |    1
-     |       6 |    2
-     |       9 |    1
-     |       8 |    0
-     |       5 |    1
-     |       3 |    3
-     |       7 |    3
-     |       0 |    0
+   3 |       0 |    0
+   5 |       1 |    1
+   8 |       2 |    2
+  12 |       3 |    3
+  16 |       4 |    0
+  20 |       5 |    1
+  24 |       6 |    2
+  28 |       7 |    3
+  22 |       8 |    0
+  15 |       9 |    1
 (10 rows)
 
-SELECT sum(unique1) over (rows between 2 preceding and 2 following exclude 
ties),
+SELECT sum(unique1) over (order by unique1 rows between 2 preceding and 2 
following exclude ties),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-   4 |       4 |    0
-   2 |       2 |    2
-   1 |       1 |    1
-   6 |       6 |    2
-   9 |       9 |    1
-   8 |       8 |    0
-   5 |       5 |    1
-   3 |       3 |    3
-   7 |       7 |    3
-   0 |       0 |    0
+   3 |       0 |    0
+   6 |       1 |    1
+  10 |       2 |    2
+  15 |       3 |    3
+  20 |       4 |    0
+  25 |       5 |    1
+  30 |       6 |    2
+  35 |       7 |    3
+  30 |       8 |    0
+  24 |       9 |    1
 (10 rows)
 
-SELECT first_value(unique1) over (ORDER BY four rows between current row and 2 
following exclude current row),
+SELECT first_value(unique1) over (ORDER BY four, unique1 rows between current 
row and 2 following exclude current row),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
  first_value | unique1 | four 
 -------------+---------+------
-           8 |       0 |    0
-           4 |       8 |    0
-           5 |       4 |    0
+           4 |       0 |    0
+           8 |       4 |    0
+           1 |       8 |    0
+           5 |       1 |    1
            9 |       5 |    1
-           1 |       9 |    1
-           6 |       1 |    1
-           2 |       6 |    2
-           3 |       2 |    2
+           2 |       9 |    1
+           6 |       2 |    2
+           3 |       6 |    2
            7 |       3 |    3
              |       7 |    3
 (10 rows)
 
-SELECT first_value(unique1) over (ORDER BY four rows between current row and 2 
following exclude group),
+SELECT first_value(unique1) over (ORDER BY four, unique1 rows between current 
row and 2 following exclude group),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
  first_value | unique1 | four 
 -------------+---------+------
-             |       0 |    0
-           5 |       8 |    0
-           5 |       4 |    0
-             |       5 |    1
-           6 |       9 |    1
-           6 |       1 |    1
+           4 |       0 |    0
+           8 |       4 |    0
+           1 |       8 |    0
+           5 |       1 |    1
+           9 |       5 |    1
+           2 |       9 |    1
+           6 |       2 |    2
            3 |       6 |    2
-           3 |       2 |    2
-             |       3 |    3
+           7 |       3 |    3
              |       7 |    3
 (10 rows)
 
-SELECT first_value(unique1) over (ORDER BY four rows between current row and 2 
following exclude ties),
+SELECT first_value(unique1) over (ORDER BY four, unique1 rows between current 
row and 2 following exclude ties),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
  first_value | unique1 | four 
 -------------+---------+------
            0 |       0 |    0
-           8 |       8 |    0
            4 |       4 |    0
+           8 |       8 |    0
+           1 |       1 |    1
            5 |       5 |    1
            9 |       9 |    1
-           1 |       1 |    1
-           6 |       6 |    2
            2 |       2 |    2
+           6 |       6 |    2
            3 |       3 |    3
            7 |       7 |    3
 (10 rows)
 
-SELECT last_value(unique1) over (ORDER BY four rows between current row and 2 
following exclude current row),
+SELECT last_value(unique1) over (ORDER BY four, unique1 rows between current 
row and 2 following exclude current row),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
  last_value | unique1 | four 
 ------------+---------+------
-          4 |       0 |    0
+          8 |       0 |    0
+          1 |       4 |    0
           5 |       8 |    0
-          9 |       4 |    0
-          1 |       5 |    1
+          9 |       1 |    1
+          2 |       5 |    1
           6 |       9 |    1
-          2 |       1 |    1
-          3 |       6 |    2
-          7 |       2 |    2
+          3 |       2 |    2
+          7 |       6 |    2
           7 |       3 |    3
             |       7 |    3
 (10 rows)
 
-SELECT last_value(unique1) over (ORDER BY four rows between current row and 2 
following exclude group),
+SELECT last_value(unique1) over (ORDER BY four, unique1 rows between current 
row and 2 following exclude group),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
  last_value | unique1 | four 
 ------------+---------+------
-            |       0 |    0
+          8 |       0 |    0
+          1 |       4 |    0
           5 |       8 |    0
-          9 |       4 |    0
-            |       5 |    1
+          9 |       1 |    1
+          2 |       5 |    1
           6 |       9 |    1
-          2 |       1 |    1
-          3 |       6 |    2
-          7 |       2 |    2
-            |       3 |    3
+          3 |       2 |    2
+          7 |       6 |    2
+          7 |       3 |    3
             |       7 |    3
 (10 rows)
 
-SELECT last_value(unique1) over (ORDER BY four rows between current row and 2 
following exclude ties),
+SELECT last_value(unique1) over (ORDER BY four, unique1 rows between current 
row and 2 following exclude ties),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
  last_value | unique1 | four 
 ------------+---------+------
-          0 |       0 |    0
+          8 |       0 |    0
+          1 |       4 |    0
           5 |       8 |    0
-          9 |       4 |    0
-          5 |       5 |    1
+          9 |       1 |    1
+          2 |       5 |    1
           6 |       9 |    1
-          2 |       1 |    1
-          3 |       6 |    2
-          7 |       2 |    2
-          3 |       3 |    3
+          3 |       2 |    2
+          7 |       6 |    2
+          7 |       3 |    3
           7 |       7 |    3
 (10 rows)
 
-SELECT sum(unique1) over (rows between 2 preceding and 1 preceding),
+SELECT sum(unique1) over (order by unique1 rows between 2 preceding and 1 
preceding),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-     |       4 |    0
-   4 |       2 |    2
-   6 |       1 |    1
-   3 |       6 |    2
-   7 |       9 |    1
-  15 |       8 |    0
-  17 |       5 |    1
-  13 |       3 |    3
-   8 |       7 |    3
-  10 |       0 |    0
+     |       0 |    0
+   0 |       1 |    1
+   1 |       2 |    2
+   3 |       3 |    3
+   5 |       4 |    0
+   7 |       5 |    1
+   9 |       6 |    2
+  11 |       7 |    3
+  13 |       8 |    0
+  15 |       9 |    1
 (10 rows)
 
-SELECT sum(unique1) over (rows between 1 following and 3 following),
+SELECT sum(unique1) over (order by unique1 rows between 1 following and 3 
following),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-   9 |       4 |    0
-  16 |       2 |    2
-  23 |       1 |    1
-  22 |       6 |    2
-  16 |       9 |    1
-  15 |       8 |    0
-  10 |       5 |    1
-   7 |       3 |    3
-   0 |       7 |    3
-     |       0 |    0
+   6 |       0 |    0
+   9 |       1 |    1
+  12 |       2 |    2
+  15 |       3 |    3
+  18 |       4 |    0
+  21 |       5 |    1
+  24 |       6 |    2
+  17 |       7 |    3
+   9 |       8 |    0
+     |       9 |    1
 (10 rows)
 
-SELECT sum(unique1) over (rows between unbounded preceding and 1 following),
+SELECT sum(unique1) over (order by unique1 rows between unbounded preceding 
and 1 following),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-   6 |       4 |    0
-   7 |       2 |    2
-  13 |       1 |    1
-  22 |       6 |    2
-  30 |       9 |    1
-  35 |       8 |    0
-  38 |       5 |    1
-  45 |       3 |    3
-  45 |       7 |    3
-  45 |       0 |    0
+   1 |       0 |    0
+   3 |       1 |    1
+   6 |       2 |    2
+  10 |       3 |    3
+  15 |       4 |    0
+  21 |       5 |    1
+  28 |       6 |    2
+  36 |       7 |    3
+  45 |       8 |    0
+  45 |       9 |    1
 (10 rows)
 
 SELECT sum(unique1) over (w range between current row and unbounded following),
@@ -1584,10 +1586,10 @@ FROM tenk1 WHERE unique1 < 10 WINDOW w AS (order by 
four);
   33 |       5 |    1
   33 |       9 |    1
   33 |       1 |    1
-  18 |       2 |    2
   18 |       6 |    2
-  10 |       7 |    3
+  18 |       2 |    2
   10 |       3 |    3
+  10 |       7 |    3
 (10 rows)
 
 SELECT sum(unique1) over (w range between unbounded preceding and current row 
exclude current row),
@@ -1645,19 +1647,19 @@ SELECT first_value(unique1) over w,
        nth_value(unique1, 2) over w AS nth_2,
        last_value(unique1) over w, unique1, four
 FROM tenk1 WHERE unique1 < 10
-WINDOW w AS (order by four range between current row and unbounded following);
+WINDOW w AS (order by unique1, four range between current row and unbounded 
following);
  first_value | nth_2 | last_value | unique1 | four 
 -------------+-------+------------+---------+------
-           0 |     8 |          7 |       0 |    0
-           0 |     8 |          7 |       8 |    0
-           0 |     8 |          7 |       4 |    0
-           5 |     9 |          7 |       5 |    1
-           5 |     9 |          7 |       9 |    1
-           5 |     9 |          7 |       1 |    1
-           6 |     2 |          7 |       6 |    2
-           6 |     2 |          7 |       2 |    2
-           3 |     7 |          7 |       3 |    3
-           3 |     7 |          7 |       7 |    3
+           0 |     1 |          9 |       0 |    0
+           1 |     2 |          9 |       1 |    1
+           2 |     3 |          9 |       2 |    2
+           3 |     4 |          9 |       3 |    3
+           4 |     5 |          9 |       4 |    0
+           5 |     6 |          9 |       5 |    1
+           6 |     7 |          9 |       6 |    2
+           7 |     8 |          9 |       7 |    3
+           8 |     9 |          9 |       8 |    0
+           9 |       |          9 |       9 |    1
 (10 rows)
 
 SELECT sum(unique1) over
@@ -1865,12 +1867,12 @@ SELECT sum(unique1) over (order by four range between 
2::int8 preceding and 1::i
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-     |       0 |    0
-     |       8 |    0
      |       4 |    0
+     |       8 |    0
+     |       0 |    0
+  12 |       1 |    1
   12 |       5 |    1
   12 |       9 |    1
-  12 |       1 |    1
   27 |       6 |    2
   27 |       2 |    2
   23 |       3 |    3
@@ -1884,14 +1886,14 @@ FROM tenk1 WHERE unique1 < 10;
 -----+---------+------
      |       3 |    3
      |       7 |    3
-  10 |       6 |    2
   10 |       2 |    2
-  18 |       9 |    1
+  10 |       6 |    2
   18 |       5 |    1
+  18 |       9 |    1
   18 |       1 |    1
   23 |       0 |    0
-  23 |       8 |    0
   23 |       4 |    0
+  23 |       8 |    0
 (10 rows)
 
 SELECT sum(unique1) over (order by four range between 2::int8 preceding and 
1::int2 preceding exclude no others),
@@ -1899,12 +1901,12 @@ SELECT sum(unique1) over (order by four range between 
2::int8 preceding and 1::i
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-     |       0 |    0
-     |       8 |    0
      |       4 |    0
+     |       8 |    0
+     |       0 |    0
+  12 |       1 |    1
   12 |       5 |    1
   12 |       9 |    1
-  12 |       1 |    1
   27 |       6 |    2
   27 |       2 |    2
   23 |       3 |    3
@@ -1916,12 +1918,12 @@ SELECT sum(unique1) over (order by four range between 
2::int8 preceding and 1::i
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-     |       0 |    0
-     |       8 |    0
      |       4 |    0
+     |       8 |    0
+     |       0 |    0
+  12 |       1 |    1
   12 |       5 |    1
   12 |       9 |    1
-  12 |       1 |    1
   27 |       6 |    2
   27 |       2 |    2
   23 |       3 |    3
@@ -1933,12 +1935,12 @@ SELECT sum(unique1) over (order by four range between 
2::int8 preceding and 1::i
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-     |       0 |    0
-     |       8 |    0
      |       4 |    0
+     |       8 |    0
+     |       0 |    0
+  12 |       1 |    1
   12 |       5 |    1
   12 |       9 |    1
-  12 |       1 |    1
   27 |       6 |    2
   27 |       2 |    2
   23 |       3 |    3
@@ -1950,12 +1952,12 @@ SELECT sum(unique1) over (order by four range between 
2::int8 preceding and 1::i
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-     |       0 |    0
-     |       8 |    0
      |       4 |    0
+     |       8 |    0
+     |       0 |    0
+  12 |       1 |    1
   12 |       5 |    1
   12 |       9 |    1
-  12 |       1 |    1
   27 |       6 |    2
   27 |       2 |    2
   23 |       3 |    3
@@ -1967,12 +1969,12 @@ SELECT sum(unique1) over (order by four range between 
2::int8 preceding and 6::i
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-  33 |       0 |    0
-  41 |       8 |    0
   37 |       4 |    0
+  41 |       8 |    0
+  33 |       0 |    0
+  31 |       1 |    1
   35 |       5 |    1
   39 |       9 |    1
-  31 |       1 |    1
   43 |       6 |    2
   39 |       2 |    2
   26 |       3 |    3
@@ -1984,12 +1986,12 @@ SELECT sum(unique1) over (order by four range between 
2::int8 preceding and 6::i
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-  33 |       0 |    0
-  33 |       8 |    0
   33 |       4 |    0
+  33 |       8 |    0
+  33 |       0 |    0
+  30 |       1 |    1
   30 |       5 |    1
   30 |       9 |    1
-  30 |       1 |    1
   37 |       6 |    2
   37 |       2 |    2
   23 |       3 |    3
@@ -2001,16 +2003,16 @@ SELECT sum(unique1) over (partition by four order by 
unique1 range between 5::in
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
+   8 |       2 |    2
+   8 |       6 |    2
+  10 |       3 |    3
+  10 |       7 |    3
    4 |       0 |    0
   12 |       4 |    0
   12 |       8 |    0
    6 |       1 |    1
   15 |       5 |    1
   14 |       9 |    1
-   8 |       2 |    2
-   8 |       6 |    2
-  10 |       3 |    3
-  10 |       7 |    3
 (10 rows)
 
 SELECT sum(unique1) over (partition by four order by unique1 range between 
5::int8 preceding and 6::int2 following
@@ -2018,16 +2020,16 @@ SELECT sum(unique1) over (partition by four order by 
unique1 range between 5::in
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
+   6 |       2 |    2
+   2 |       6 |    2
+   7 |       3 |    3
+   3 |       7 |    3
    4 |       0 |    0
    8 |       4 |    0
    4 |       8 |    0
    5 |       1 |    1
   10 |       5 |    1
    5 |       9 |    1
-   6 |       2 |    2
-   2 |       6 |    2
-   7 |       3 |    3
-   3 |       7 |    3
 (10 rows)
 
 select sum(salary) over (order by enroll_date range between '1 year'::interval 
preceding and '1 year'::interval following),
@@ -2417,6 +2419,8 @@ create temp table numerics(
     f_float8 float8,
     f_numeric numeric
 );
+NOTICE:  Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'id' 
as the Apache Cloudberry data distribution key for this table.
+HINT:  The 'DISTRIBUTED BY' clause determines the distribution of data. Make 
sure column(s) chosen are the optimal data distribution key to minimize skew.
 insert into numerics values
 (0, '-infinity', '-infinity', '-infinity'),
 (1, -3, -3, -3),
@@ -2730,6 +2734,8 @@ create temp table datetimes(
     f_timestamptz timestamptz,
     f_timestamp timestamp
 );
+NOTICE:  Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'id' 
as the Apache Cloudberry data distribution key for this table.
+HINT:  The 'DISTRIBUTED BY' clause determines the distribution of data. Make 
sure column(s) chosen are the optimal data distribution key to minimize skew.
 insert into datetimes values
 (1, '11:00', '11:00 BST', '1 year', '2000-10-19 10:23:54+01', '2000-10-19 
10:23:54'),
 (2, '12:00', '12:00 BST', '2 years', '2001-10-19 10:23:54+01', '2001-10-19 
10:23:54'),
@@ -2805,8 +2811,8 @@ window w as (order by f_timetz desc range between
   9 | 19:00:00+01 |          10 |          7
   8 | 18:00:00+01 |           9 |          7
   7 | 17:00:00+01 |           8 |          6
-  6 | 15:00:00+01 |           5 |          3
   5 | 15:00:00+01 |           5 |          3
+  6 | 15:00:00+01 |           5 |          3
   4 | 14:00:00+01 |           5 |          2
   3 | 13:00:00+01 |           4 |          1
   2 | 12:00:00+01 |           3 |          1
@@ -2841,8 +2847,8 @@ window w as (order by f_interval desc range between
   9 | @ 9 years  |          10 |          8
   8 | @ 8 years  |           9 |          7
   7 | @ 7 years  |           8 |          7
-  6 | @ 5 years  |           5 |          4
   5 | @ 5 years  |           5 |          4
+  6 | @ 5 years  |           5 |          4
   4 | @ 4 years  |           5 |          3
   3 | @ 3 years  |           4 |          2
   2 | @ 2 years  |           3 |          1
@@ -2880,8 +2886,8 @@ window w as (order by f_timestamptz desc range between
   6 | Tue Oct 19 02:23:54 2004 PDT |           7 |          5
   5 | Sun Oct 19 02:23:54 2003 PDT |           6 |          4
   4 | Sat Oct 19 02:23:54 2002 PDT |           5 |          3
-  3 | Fri Oct 19 02:23:54 2001 PDT |           4 |          1
   2 | Fri Oct 19 02:23:54 2001 PDT |           4 |          1
+  3 | Fri Oct 19 02:23:54 2001 PDT |           4 |          1
   1 | Thu Oct 19 02:23:54 2000 PDT |           2 |          1
 (10 rows)
 
@@ -2916,8 +2922,8 @@ window w as (order by f_timestamp desc range between
   6 | Tue Oct 19 10:23:54 2004 |           7 |          5
   5 | Sun Oct 19 10:23:54 2003 |           6 |          4
   4 | Sat Oct 19 10:23:54 2002 |           5 |          3
-  3 | Fri Oct 19 10:23:54 2001 |           4 |          1
   2 | Fri Oct 19 10:23:54 2001 |           4 |          1
+  3 | Fri Oct 19 10:23:54 2001 |           4 |          1
   1 | Thu Oct 19 10:23:54 2000 |           2 |          1
 (10 rows)
 
@@ -2964,12 +2970,12 @@ SELECT sum(unique1) over (order by four groups between 
unbounded preceding and c
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-  12 |       0 |    0
-  12 |       8 |    0
   12 |       4 |    0
+  12 |       8 |    0
+  12 |       0 |    0
+  27 |       1 |    1
   27 |       5 |    1
   27 |       9 |    1
-  27 |       1 |    1
   35 |       6 |    2
   35 |       2 |    2
   45 |       3 |    3
@@ -2981,12 +2987,12 @@ SELECT sum(unique1) over (order by four groups between 
unbounded preceding and u
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-  45 |       0 |    0
-  45 |       8 |    0
   45 |       4 |    0
+  45 |       8 |    0
+  45 |       0 |    0
+  45 |       1 |    1
   45 |       5 |    1
   45 |       9 |    1
-  45 |       1 |    1
   45 |       6 |    2
   45 |       2 |    2
   45 |       3 |    3
@@ -2998,12 +3004,12 @@ SELECT sum(unique1) over (order by four groups between 
current row and unbounded
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-  45 |       0 |    0
-  45 |       8 |    0
   45 |       4 |    0
+  45 |       8 |    0
+  45 |       0 |    0
+  33 |       1 |    1
   33 |       5 |    1
   33 |       9 |    1
-  33 |       1 |    1
   18 |       6 |    2
   18 |       2 |    2
   10 |       3 |    3
@@ -3015,12 +3021,12 @@ SELECT sum(unique1) over (order by four groups between 
1 preceding and unbounded
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-  45 |       0 |    0
-  45 |       8 |    0
   45 |       4 |    0
+  45 |       8 |    0
+  45 |       0 |    0
+  45 |       1 |    1
   45 |       5 |    1
   45 |       9 |    1
-  45 |       1 |    1
   33 |       6 |    2
   33 |       2 |    2
   18 |       3 |    3
@@ -3032,12 +3038,12 @@ SELECT sum(unique1) over (order by four groups between 
1 following and unbounded
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-  33 |       0 |    0
-  33 |       8 |    0
   33 |       4 |    0
+  33 |       8 |    0
+  33 |       0 |    0
+  18 |       1 |    1
   18 |       5 |    1
   18 |       9 |    1
-  18 |       1 |    1
   10 |       6 |    2
   10 |       2 |    2
      |       3 |    3
@@ -3049,12 +3055,12 @@ SELECT sum(unique1) over (order by four groups between 
unbounded preceding and 2
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-  35 |       0 |    0
-  35 |       8 |    0
   35 |       4 |    0
+  35 |       8 |    0
+  35 |       0 |    0
+  45 |       1 |    1
   45 |       5 |    1
   45 |       9 |    1
-  45 |       1 |    1
   45 |       6 |    2
   45 |       2 |    2
   45 |       3 |    3
@@ -3066,12 +3072,12 @@ SELECT sum(unique1) over (order by four groups between 
2 preceding and 1 precedi
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-     |       0 |    0
-     |       8 |    0
      |       4 |    0
+     |       8 |    0
+     |       0 |    0
+  12 |       1 |    1
   12 |       5 |    1
   12 |       9 |    1
-  12 |       1 |    1
   27 |       6 |    2
   27 |       2 |    2
   23 |       3 |    3
@@ -3083,12 +3089,12 @@ SELECT sum(unique1) over (order by four groups between 
2 preceding and 1 followi
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-  27 |       0 |    0
-  27 |       8 |    0
   27 |       4 |    0
+  27 |       8 |    0
+  27 |       0 |    0
+  35 |       1 |    1
   35 |       5 |    1
   35 |       9 |    1
-  35 |       1 |    1
   45 |       6 |    2
   45 |       2 |    2
   33 |       3 |    3
@@ -3100,12 +3106,12 @@ SELECT sum(unique1) over (order by four groups between 
0 preceding and 0 followi
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-  12 |       0 |    0
-  12 |       8 |    0
   12 |       4 |    0
+  12 |       8 |    0
+  12 |       0 |    0
+  15 |       1 |    1
   15 |       5 |    1
   15 |       9 |    1
-  15 |       1 |    1
    8 |       6 |    2
    8 |       2 |    2
   10 |       3 |    3
@@ -3117,12 +3123,12 @@ SELECT sum(unique1) over (order by four groups between 
2 preceding and 1 followi
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-  27 |       0 |    0
-  19 |       8 |    0
   23 |       4 |    0
+  19 |       8 |    0
+  27 |       0 |    0
+  34 |       1 |    1
   30 |       5 |    1
   26 |       9 |    1
-  34 |       1 |    1
   39 |       6 |    2
   43 |       2 |    2
   30 |       3 |    3
@@ -3134,12 +3140,12 @@ SELECT sum(unique1) over (order by four groups between 
2 preceding and 1 followi
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-  15 |       0 |    0
-  15 |       8 |    0
   15 |       4 |    0
+  15 |       8 |    0
+  15 |       0 |    0
+  20 |       1 |    1
   20 |       5 |    1
   20 |       9 |    1
-  20 |       1 |    1
   37 |       6 |    2
   37 |       2 |    2
   23 |       3 |    3
@@ -3151,12 +3157,12 @@ SELECT sum(unique1) over (order by four groups between 
2 preceding and 1 followi
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four 
 -----+---------+------
-  15 |       0 |    0
-  23 |       8 |    0
   19 |       4 |    0
+  23 |       8 |    0
+  15 |       0 |    0
+  21 |       1 |    1
   25 |       5 |    1
   29 |       9 |    1
-  21 |       1 |    1
   43 |       6 |    2
   39 |       2 |    2
   26 |       3 |    3
@@ -3168,15 +3174,15 @@ SELECT sum(unique1) over (partition by ten
 FROM tenk1 WHERE unique1 < 10;
  sum | unique1 | four | ten 
 -----+---------+------+-----
-   0 |       0 |    0 |   0
-   1 |       1 |    1 |   1
    2 |       2 |    2 |   2
    3 |       3 |    3 |   3
    4 |       4 |    0 |   4
-   5 |       5 |    1 |   5
-   6 |       6 |    2 |   6
    7 |       7 |    3 |   7
    8 |       8 |    0 |   8
+   0 |       0 |    0 |   0
+   1 |       1 |    1 |   1
+   5 |       5 |    1 |   5
+   6 |       6 |    2 |   6
    9 |       9 |    1 |   9
 (10 rows)
 
@@ -3190,10 +3196,10 @@ FROM tenk1 WHERE unique1 < 10;
      |       2 |    2 |   2
      |       3 |    3 |   3
      |       4 |    0 |   4
-     |       5 |    1 |   5
-     |       6 |    2 |   6
      |       7 |    3 |   7
      |       8 |    0 |   8
+     |       5 |    1 |   5
+     |       6 |    2 |   6
      |       9 |    1 |   9
 (10 rows)
 
@@ -3204,14 +3210,14 @@ FROM tenk1 WHERE unique1 < 10;
 -----+---------+------+-----
      |       0 |    0 |   0
      |       1 |    1 |   1
+     |       5 |    1 |   5
+     |       6 |    2 |   6
+     |       9 |    1 |   9
      |       2 |    2 |   2
      |       3 |    3 |   3
      |       4 |    0 |   4
-     |       5 |    1 |   5
-     |       6 |    2 |   6
      |       7 |    3 |   7
      |       8 |    0 |   8
-     |       9 |    1 |   9
 (10 rows)
 
 SELECT sum(unique1) over (partition by ten
@@ -3221,14 +3227,14 @@ FROM tenk1 WHERE unique1 < 10;
 -----+---------+------+-----
    0 |       0 |    0 |   0
    1 |       1 |    1 |   1
+   5 |       5 |    1 |   5
+   6 |       6 |    2 |   6
+   9 |       9 |    1 |   9
    2 |       2 |    2 |   2
    3 |       3 |    3 |   3
    4 |       4 |    0 |   4
-   5 |       5 |    1 |   5
-   6 |       6 |    2 |   6
    7 |       7 |    3 |   7
    8 |       8 |    0 |   8
-   9 |       9 |    1 |   9
 (10 rows)
 
 select first_value(salary) over(order by enroll_date groups between 1 
preceding and 1 following),
@@ -3510,6 +3516,8 @@ DETAIL:  Falling back to Postgres-based planner because 
GPORCA does not support
 
 -- check some degenerate cases
 create temp table t1 (f1 int, f2 int8);
+NOTICE:  Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'f1' 
as the Apache Cloudberry data distribution key for this table.
+HINT:  The 'DISTRIBUTED BY' clause determines the distribution of data. Make 
sure column(s) chosen are the optimal data distribution key to minimize skew.
 insert into t1 values (1,1),(1,2),(2,2);
 select f1, sum(f1) over (partition by f1
                          range between 1 preceding and 1 following)
@@ -3531,7 +3539,7 @@ from t1 where f1 = f2;
                Sort Key: f1, f2
                ->  Seq Scan on t1
                      Filter: (f1 = f2)
- Optimizer: Pivotal Optimizer (GPORCA)
+ Optimizer: GPORCA
 (9 rows)
 
 select f1, sum(f1) over (partition by f1 order by f2
@@ -3548,8 +3556,8 @@ select f1, sum(f1) over (partition by f1, f1 order by f2
 from t1 where f1 = f2;
  f1 | sum 
 ----+-----
-  1 |    
   2 |    
+  1 |    
 (2 rows)
 
 select f1, sum(f1) over (partition by f1, f2 order by f2
@@ -3581,7 +3589,7 @@ from t1 where f1 = f2;
                Sort Key: f1, f2
                ->  Seq Scan on t1
                      Filter: (f1 = f2)
- Optimizer: Pivotal Optimizer (GPORCA)
+ Optimizer: GPORCA
 (9 rows)
 
 select f1, sum(f1) over (partition by f1 order by f2
@@ -3589,8 +3597,8 @@ select f1, sum(f1) over (partition by f1 order by f2
 from t1 where f1 = f2;
  f1 | sum 
 ----+-----
-  1 |   1
   2 |   2
+  1 |   1
 (2 rows)
 
 select f1, sum(f1) over (partition by f1, f1 order by f2
@@ -3598,8 +3606,8 @@ select f1, sum(f1) over (partition by f1, f1 order by f2
 from t1 where f1 = f2;
  f1 | sum 
 ----+-----
-  1 |    
   2 |    
+  1 |    
 (2 rows)
 
 select f1, sum(f1) over (partition by f1, f2 order by f2
@@ -3607,8 +3615,8 @@ select f1, sum(f1) over (partition by f1, f2 order by f2
 from t1 where f1 = f2;
  f1 | sum 
 ----+-----
-  1 |    
   2 |    
+  1 |    
 (2 rows)
 
 -- ordering by a non-integer constant is allowed
@@ -3714,7 +3722,7 @@ WHERE depname = 'sales';
                                  Sort Key: depname
                                  ->  Seq Scan on empsalary
                                        Filter: ((depname)::text = 
'sales'::text)
- Optimizer: Pivotal Optimizer (GPORCA) version 3.83.0
+ Optimizer: GPORCA
 (13 rows)
 
 -- pushdown is unsafe because there's a PARTITION BY clause without depname:
@@ -3743,7 +3751,7 @@ WHERE depname = 'sales';
                                        ->  Redistribute Motion 3:3  (slice3; 
segments: 3)
                                              Hash Key: enroll_date
                                              ->  Seq Scan on empsalary
- Optimizer: Pivotal Optimizer (GPORCA) version 3.23.0
+ Optimizer: GPORCA
 (17 rows)
 
 -- pushdown is unsafe because the subquery contains window functions and the 
qual is volatile:
@@ -3768,7 +3776,7 @@ WHERE depname = 'sales' OR RANDOM() > 0.5;
                                  Sort Key: depname
                                  ->  Seq Scan on empsalary
                                        Filter: (((depname)::text = 
'sales'::text) OR (random() > '0.5'::double precision))
- Optimizer: Pivotal Optimizer (GPORCA)
+ Optimizer: GPORCA
 (13 rows)
 
 -- Test Sort node collapsing
@@ -3794,7 +3802,7 @@ WHERE depname = 'sales';
                            Sort Key: depname, empno
                            ->  Seq Scan on empsalary
                                  Filter: ((depname)::text = 'sales'::text)
- Optimizer: Pivotal Optimizer (GPORCA)
+ Optimizer: GPORCA
 (14 rows)
 
 -- Test Sort node reordering
@@ -3817,7 +3825,7 @@ FROM empsalary;
                      ->  Sort
                            Sort Key: depname, salary, enroll_date
                            ->  Seq Scan on empsalary
- Optimizer: Pivotal Optimizer (GPORCA)
+ Optimizer: GPORCA
 (13 rows)
 
 -- Test incremental sorting
@@ -3831,9 +3839,7 @@ SELECT * FROM
           row_number() OVER (PARTITION BY depname ORDER BY enroll_date DESC) 
AS last_emp
    FROM empsalary) emp
 WHERE first_emp = 1 OR last_emp = 1;
-NOTICE:  One or more columns in the following table(s) do not have statistics: 
empsalary
-HINT:  For non-partitioned tables, run analyze <table_name>(<column_list>). 
For partitioned tables, run analyze rootpartition <table_name>(<column_list>). 
See log for columns missing statistics.
-                                    QUERY PLAN
+                                    QUERY PLAN                                 
   
 
----------------------------------------------------------------------------------
  Gather Motion 3:1  (slice1; segments: 3)
    ->  Result
@@ -3849,7 +3855,7 @@ HINT:  For non-partitioned tables, run analyze 
<table_name>(<column_list>). For
                            ->  Sort
                                  Sort Key: depname, enroll_date
                                  ->  Seq Scan on empsalary
- Optimizer: Pivotal Optimizer (GPORCA)
+ Optimizer: GPORCA
 (15 rows)
 
 SELECT * FROM
@@ -3861,8 +3867,6 @@ SELECT * FROM
           row_number() OVER (PARTITION BY depname ORDER BY enroll_date DESC) 
AS last_emp
    FROM empsalary) emp
 WHERE first_emp = 1 OR last_emp = 1;
-NOTICE:  One or more columns in the following table(s) do not have statistics: 
empsalary
-HINT:  For non-partitioned tables, run analyze <table_name>(<column_list>). 
For partitioned tables, run analyze rootpartition <table_name>(<column_list>). 
See log for columns missing statistics.
   depname  | empno | salary | enroll_date | first_emp | last_emp 
 -----------+-------+--------+-------------+-----------+----------
  develop   |     9 |   4500 | 01-01-2008  |         4 |        1
@@ -4760,10 +4764,10 @@ AS $$
     WINDOW w AS (ORDER BY s ROWS BETWEEN CURRENT ROW AND GROUP_SIZE FOLLOWING)
 $$ LANGUAGE SQL STABLE;
 EXPLAIN (costs off) SELECT * FROM pg_temp.f(2);
-              QUERY PLAN               
----------------------------------------
+     QUERY PLAN     
+--------------------
  Function Scan on f
- Optimizer: Pivotal Optimizer (GPORCA)
+ Optimizer: GPORCA
 (2 rows)
 
 SELECT * FROM pg_temp.f(2);
diff --git a/src/test/regress/expected/window_parallel.out 
b/src/test/regress/expected/window_parallel.out
new file mode 100644
index 00000000000..bd4b9161c1b
--- /dev/null
+++ b/src/test/regress/expected/window_parallel.out
@@ -0,0 +1,869 @@
+set force_parallel_mode = 0;
+set optimizer = off;
+create schema window_parallel;
+set search_path to window_parallel;
+set gp_appendonly_insert_files = 4;
+set min_parallel_table_scan_size = 0;
+--
+-- Test of Parallel process of Window Functions.
+--
+CREATE TABLE empsalary (
+    depname varchar,
+    empno bigint,
+    salary int,
+    enroll_date date
+);
+NOTICE:  Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 
'depname' as the Apache Cloudberry data distribution key for this table.
+HINT:  The 'DISTRIBUTED BY' clause determines the distribution of data. Make 
sure column(s) chosen are the optimal data distribution key to minimize skew.
+INSERT INTO empsalary VALUES
+('develop', 10, 5200, '2007-08-01'),
+('sales', 1, 5000, '2006-10-01'),
+('personnel', 5, 3500, '2007-12-10'),
+('sales', 4, 4800, '2007-08-08'),
+('personnel', 2, 3900, '2006-12-23'),
+('develop', 7, 4200, '2008-01-01'),
+('develop', 9, 4500, '2008-01-01'),
+('sales', 3, 4800, '2007-08-01'),
+('develop', 8, 6000, '2006-10-01'),
+('develop', 11, 5200, '2007-08-15');
+-- w1
+set enable_parallel = off;
+EXPLAIN(COSTS OFF)
+SELECT depname, empno, salary, sum(salary) OVER (PARTITION BY depname) FROM 
empsalary ORDER BY depname, salary;
+                  QUERY PLAN                   
+-----------------------------------------------
+ Gather Motion 3:1  (slice1; segments: 3)
+   Merge Key: depname, salary
+   ->  Sort
+         Sort Key: depname, salary
+         ->  WindowAgg
+               Partition By: depname
+               ->  Sort
+                     Sort Key: depname
+                     ->  Seq Scan on empsalary
+ Optimizer: Postgres query optimizer
+(10 rows)
+
+SELECT depname, empno, salary, sum(salary) OVER (PARTITION BY depname) FROM 
empsalary ORDER BY depname, salary;
+  depname  | empno | salary |  sum  
+-----------+-------+--------+-------
+ develop   |     7 |   4200 | 25100
+ develop   |     9 |   4500 | 25100
+ develop   |    11 |   5200 | 25100
+ develop   |    10 |   5200 | 25100
+ develop   |     8 |   6000 | 25100
+ personnel |     5 |   3500 |  7400
+ personnel |     2 |   3900 |  7400
+ sales     |     3 |   4800 | 14600
+ sales     |     4 |   4800 | 14600
+ sales     |     1 |   5000 | 14600
+(10 rows)
+
+set enable_parallel = on;
+EXPLAIN(COSTS OFF)
+SELECT depname, empno, salary, sum(salary) OVER (PARTITION BY depname) FROM 
empsalary ORDER BY depname, salary;
+                               QUERY PLAN                               
+------------------------------------------------------------------------
+ Gather Motion 6:1  (slice1; segments: 6)
+   Merge Key: depname, salary
+   ->  Sort
+         Sort Key: depname, salary
+         ->  WindowAgg
+               Partition By: depname
+               ->  Sort
+                     Sort Key: depname
+                     ->  Redistribute Motion 6:6  (slice2; segments: 6)
+                           Hash Key: depname
+                           Hash Module: 3
+                           ->  Parallel Seq Scan on empsalary
+ Optimizer: Postgres query optimizer
+(13 rows)
+
+SELECT depname, empno, salary, sum(salary) OVER (PARTITION BY depname) FROM 
empsalary ORDER BY depname, salary;
+  depname  | empno | salary |  sum  
+-----------+-------+--------+-------
+ develop   |     7 |   4200 | 25100
+ develop   |     9 |   4500 | 25100
+ develop   |    10 |   5200 | 25100
+ develop   |    11 |   5200 | 25100
+ develop   |     8 |   6000 | 25100
+ personnel |     5 |   3500 |  7400
+ personnel |     2 |   3900 |  7400
+ sales     |     4 |   4800 | 14600
+ sales     |     3 |   4800 | 14600
+ sales     |     1 |   5000 | 14600
+(10 rows)
+
+-- w2
+set enable_parallel = off;
+EXPLAIN(COSTS OFF)
+SELECT depname, empno, salary, rank() OVER (PARTITION BY depname ORDER BY 
salary) FROM empsalary;
+                QUERY PLAN                
+------------------------------------------
+ Gather Motion 3:1  (slice1; segments: 3)
+   ->  WindowAgg
+         Partition By: depname
+         Order By: salary
+         ->  Sort
+               Sort Key: depname, salary
+               ->  Seq Scan on empsalary
+ Optimizer: Postgres query optimizer
+(8 rows)
+
+SELECT depname, empno, salary, rank() OVER (PARTITION BY depname ORDER BY 
salary) FROM empsalary;
+  depname  | empno | salary | rank 
+-----------+-------+--------+------
+ develop   |     7 |   4200 |    1
+ develop   |     9 |   4500 |    2
+ develop   |    11 |   5200 |    3
+ develop   |    10 |   5200 |    3
+ develop   |     8 |   6000 |    5
+ personnel |     5 |   3500 |    1
+ personnel |     2 |   3900 |    2
+ sales     |     3 |   4800 |    1
+ sales     |     4 |   4800 |    1
+ sales     |     1 |   5000 |    3
+(10 rows)
+
+set enable_parallel = on;
+EXPLAIN(COSTS OFF)
+SELECT depname, empno, salary, rank() OVER (PARTITION BY depname ORDER BY 
salary) FROM empsalary;
+                            QUERY PLAN                            
+------------------------------------------------------------------
+ Gather Motion 6:1  (slice1; segments: 6)
+   ->  WindowAgg
+         Partition By: depname
+         Order By: salary
+         ->  Sort
+               Sort Key: depname, salary
+               ->  Redistribute Motion 6:6  (slice2; segments: 6)
+                     Hash Key: depname
+                     Hash Module: 3
+                     ->  Parallel Seq Scan on empsalary
+ Optimizer: Postgres query optimizer
+(11 rows)
+
+SELECT depname, empno, salary, rank() OVER (PARTITION BY depname ORDER BY 
salary) FROM empsalary;
+  depname  | empno | salary | rank 
+-----------+-------+--------+------
+ personnel |     5 |   3500 |    1
+ personnel |     2 |   3900 |    2
+ sales     |     4 |   4800 |    1
+ sales     |     3 |   4800 |    1
+ sales     |     1 |   5000 |    3
+ develop   |     7 |   4200 |    1
+ develop   |     9 |   4500 |    2
+ develop   |    10 |   5200 |    3
+ develop   |    11 |   5200 |    3
+ develop   |     8 |   6000 |    5
+(10 rows)
+
+-- w3
+set enable_parallel = off;
+EXPLAIN(COSTS OFF)
+SELECT depname, empno, salary, sum(salary) OVER w FROM empsalary WINDOW w AS 
(PARTITION BY depname);
+                QUERY PLAN                
+------------------------------------------
+ Gather Motion 3:1  (slice1; segments: 3)
+   ->  WindowAgg
+         Partition By: depname
+         ->  Sort
+               Sort Key: depname
+               ->  Seq Scan on empsalary
+ Optimizer: Postgres query optimizer
+(7 rows)
+
+SELECT depname, empno, salary, sum(salary) OVER w FROM empsalary WINDOW w AS 
(PARTITION BY depname);
+  depname  | empno | salary |  sum  
+-----------+-------+--------+-------
+ develop   |    11 |   5200 | 25100
+ develop   |     7 |   4200 | 25100
+ develop   |     9 |   4500 | 25100
+ develop   |     8 |   6000 | 25100
+ develop   |    10 |   5200 | 25100
+ personnel |     5 |   3500 |  7400
+ personnel |     2 |   3900 |  7400
+ sales     |     3 |   4800 | 14600
+ sales     |     1 |   5000 | 14600
+ sales     |     4 |   4800 | 14600
+(10 rows)
+
+set enable_parallel = on;
+EXPLAIN(COSTS OFF)
+SELECT depname, empno, salary, sum(salary) OVER w FROM empsalary WINDOW w AS 
(PARTITION BY depname);
+                            QUERY PLAN                            
+------------------------------------------------------------------
+ Gather Motion 6:1  (slice1; segments: 6)
+   ->  WindowAgg
+         Partition By: depname
+         ->  Sort
+               Sort Key: depname
+               ->  Redistribute Motion 6:6  (slice2; segments: 6)
+                     Hash Key: depname
+                     Hash Module: 3
+                     ->  Parallel Seq Scan on empsalary
+ Optimizer: Postgres query optimizer
+(10 rows)
+
+SELECT depname, empno, salary, sum(salary) OVER w FROM empsalary WINDOW w AS 
(PARTITION BY depname);
+  depname  | empno | salary |  sum  
+-----------+-------+--------+-------
+ develop   |    10 |   5200 | 25100
+ develop   |     7 |   4200 | 25100
+ develop   |     9 |   4500 | 25100
+ develop   |     8 |   6000 | 25100
+ develop   |    11 |   5200 | 25100
+ personnel |     5 |   3500 |  7400
+ personnel |     2 |   3900 |  7400
+ sales     |     1 |   5000 | 14600
+ sales     |     4 |   4800 | 14600
+ sales     |     3 |   4800 | 14600
+(10 rows)
+
+-- w4
+set enable_parallel = off;
+EXPLAIN(COSTS OFF)
+SELECT depname, empno, salary, rank() OVER w FROM empsalary WINDOW w AS 
(PARTITION BY depname ORDER BY salary) ORDER BY rank() OVER w;
+                  QUERY PLAN                   
+-----------------------------------------------
+ Gather Motion 3:1  (slice1; segments: 3)
+   Merge Key: (rank() OVER (?))
+   ->  Sort
+         Sort Key: (rank() OVER (?))
+         ->  WindowAgg
+               Partition By: depname
+               Order By: salary
+               ->  Sort
+                     Sort Key: depname, salary
+                     ->  Seq Scan on empsalary
+ Optimizer: Postgres query optimizer
+(11 rows)
+
+SELECT depname, empno, salary, rank() OVER w FROM empsalary WINDOW w AS 
(PARTITION BY depname ORDER BY salary) ORDER BY rank() OVER w;
+  depname  | empno | salary | rank 
+-----------+-------+--------+------
+ develop   |     7 |   4200 |    1
+ personnel |     5 |   3500 |    1
+ sales     |     3 |   4800 |    1
+ sales     |     4 |   4800 |    1
+ personnel |     2 |   3900 |    2
+ develop   |     9 |   4500 |    2
+ sales     |     1 |   5000 |    3
+ develop   |    11 |   5200 |    3
+ develop   |    10 |   5200 |    3
+ develop   |     8 |   6000 |    5
+(10 rows)
+
+set enable_parallel = on;
+EXPLAIN(COSTS OFF)
+SELECT depname, empno, salary, rank() OVER w FROM empsalary WINDOW w AS 
(PARTITION BY depname ORDER BY salary) ORDER BY rank() OVER w;
+                               QUERY PLAN                               
+------------------------------------------------------------------------
+ Gather Motion 6:1  (slice1; segments: 6)
+   Merge Key: (rank() OVER (?))
+   ->  Sort
+         Sort Key: (rank() OVER (?))
+         ->  WindowAgg
+               Partition By: depname
+               Order By: salary
+               ->  Sort
+                     Sort Key: depname, salary
+                     ->  Redistribute Motion 6:6  (slice2; segments: 6)
+                           Hash Key: depname
+                           Hash Module: 3
+                           ->  Parallel Seq Scan on empsalary
+ Optimizer: Postgres query optimizer
+(14 rows)
+
+SELECT depname, empno, salary, rank() OVER w FROM empsalary WINDOW w AS 
(PARTITION BY depname ORDER BY salary) ORDER BY rank() OVER w;
+  depname  | empno | salary | rank 
+-----------+-------+--------+------
+ personnel |     5 |   3500 |    1
+ sales     |     4 |   4800 |    1
+ sales     |     3 |   4800 |    1
+ develop   |     7 |   4200 |    1
+ develop   |     9 |   4500 |    2
+ personnel |     2 |   3900 |    2
+ sales     |     1 |   5000 |    3
+ develop   |    10 |   5200 |    3
+ develop   |    11 |   5200 |    3
+ develop   |     8 |   6000 |    5
+(10 rows)
+
+-- w5
+set enable_parallel = off;
+EXPLAIN(COSTS OFF)
+SELECT sum(salary),
+       row_number() OVER (ORDER BY depname),
+       sum(sum(salary)) OVER (ORDER BY depname DESC)
+FROM empsalary GROUP BY depname;
+                         QUERY PLAN                         
+------------------------------------------------------------
+ WindowAgg
+   Order By: depname
+   ->  Sort
+         Sort Key: depname
+         ->  WindowAgg
+               Order By: depname
+               ->  Gather Motion 3:1  (slice1; segments: 3)
+                     Merge Key: depname
+                     ->  Sort
+                           Sort Key: depname DESC
+                           ->  HashAggregate
+                                 Group Key: depname
+                                 ->  Seq Scan on empsalary
+ Optimizer: Postgres query optimizer
+(14 rows)
+
+SELECT sum(salary),
+       row_number() OVER (ORDER BY depname),
+       sum(sum(salary)) OVER (ORDER BY depname DESC)
+FROM empsalary GROUP BY depname;
+  sum  | row_number |  sum  
+-------+------------+-------
+ 25100 |          1 | 47100
+  7400 |          2 | 22000
+ 14600 |          3 | 14600
+(3 rows)
+
+set enable_parallel = on;
+EXPLAIN(COSTS OFF)
+SELECT sum(salary),
+       row_number() OVER (ORDER BY depname),
+       sum(sum(salary)) OVER (ORDER BY depname DESC)
+FROM empsalary GROUP BY depname;
+                         QUERY PLAN                         
+------------------------------------------------------------
+ WindowAgg
+   Order By: depname
+   ->  Sort
+         Sort Key: depname
+         ->  WindowAgg
+               Order By: depname
+               ->  Gather Motion 3:1  (slice1; segments: 3)
+                     Merge Key: depname
+                     ->  Sort
+                           Sort Key: depname DESC
+                           ->  HashAggregate
+                                 Group Key: depname
+                                 ->  Seq Scan on empsalary
+ Optimizer: Postgres query optimizer
+(14 rows)
+
+SELECT sum(salary),
+       row_number() OVER (ORDER BY depname),
+       sum(sum(salary)) OVER (ORDER BY depname DESC)
+FROM empsalary GROUP BY depname;
+  sum  | row_number |  sum  
+-------+------------+-------
+ 25100 |          1 | 47100
+  7400 |          2 | 22000
+ 14600 |          3 | 14600
+(3 rows)
+
+-- w6
+set enable_parallel = off;
+EXPLAIN(COSTS OFF)
+-- identical windows with different names
+SELECT sum(salary) OVER w1, count(*) OVER w2
+FROM empsalary WINDOW w1 AS (ORDER BY salary), w2 AS (ORDER BY salary);
+                      QUERY PLAN                      
+------------------------------------------------------
+ WindowAgg
+   Order By: salary
+   ->  WindowAgg
+         Order By: salary
+         ->  Gather Motion 3:1  (slice1; segments: 3)
+               Merge Key: salary
+               ->  Sort
+                     Sort Key: salary
+                     ->  Seq Scan on empsalary
+ Optimizer: Postgres query optimizer
+(10 rows)
+
+SELECT sum(salary) OVER w1, count(*) OVER w2
+FROM empsalary WINDOW w1 AS (ORDER BY salary), w2 AS (ORDER BY salary);
+  sum  | count 
+-------+-------
+  3500 |     1
+  7400 |     2
+ 11600 |     3
+ 16100 |     4
+ 25700 |     6
+ 25700 |     6
+ 30700 |     7
+ 41100 |     9
+ 41100 |     9
+ 47100 |    10
+(10 rows)
+
+set enable_parallel = on;
+EXPLAIN(COSTS OFF)
+-- identical windows with different names
+SELECT sum(salary) OVER w1, count(*) OVER w2
+FROM empsalary WINDOW w1 AS (ORDER BY salary), w2 AS (ORDER BY salary);
+                       QUERY PLAN                       
+--------------------------------------------------------
+ WindowAgg
+   Order By: salary
+   ->  WindowAgg
+         Order By: salary
+         ->  Gather Motion 6:1  (slice1; segments: 6)
+               Merge Key: salary
+               ->  Sort
+                     Sort Key: salary
+                     ->  Parallel Seq Scan on empsalary
+ Optimizer: Postgres query optimizer
+(10 rows)
+
+SELECT sum(salary) OVER w1, count(*) OVER w2
+FROM empsalary WINDOW w1 AS (ORDER BY salary), w2 AS (ORDER BY salary);
+  sum  | count 
+-------+-------
+  3500 |     1
+  7400 |     2
+ 11600 |     3
+ 16100 |     4
+ 25700 |     6
+ 25700 |     6
+ 30700 |     7
+ 41100 |     9
+ 41100 |     9
+ 47100 |    10
+(10 rows)
+
+-- w7
+-- mixture of agg/wfunc in the same window
+set enable_parallel = off;
+EXPLAIN(COSTS OFF)
+SELECT sum(salary) OVER w, rank() OVER w FROM empsalary WINDOW w AS (PARTITION 
BY depname ORDER BY salary DESC);
+                  QUERY PLAN                  
+----------------------------------------------
+ Gather Motion 3:1  (slice1; segments: 3)
+   ->  WindowAgg
+         Partition By: depname
+         Order By: salary
+         ->  Sort
+               Sort Key: depname, salary DESC
+               ->  Seq Scan on empsalary
+ Optimizer: Postgres query optimizer
+(8 rows)
+
+SELECT sum(salary) OVER w, rank() OVER w FROM empsalary WINDOW w AS (PARTITION 
BY depname ORDER BY salary DESC);
+  sum  | rank 
+-------+------
+  6000 |    1
+ 16400 |    2
+ 16400 |    2
+ 20900 |    4
+ 25100 |    5
+  3900 |    1
+  7400 |    2
+  5000 |    1
+ 14600 |    2
+ 14600 |    2
+(10 rows)
+
+set enable_parallel = on;
+EXPLAIN(COSTS OFF)
+SELECT sum(salary) OVER w, rank() OVER w FROM empsalary WINDOW w AS (PARTITION 
BY depname ORDER BY salary DESC);
+                            QUERY PLAN                            
+------------------------------------------------------------------
+ Gather Motion 6:1  (slice1; segments: 6)
+   ->  WindowAgg
+         Partition By: depname
+         Order By: salary
+         ->  Sort
+               Sort Key: depname, salary DESC
+               ->  Redistribute Motion 6:6  (slice2; segments: 6)
+                     Hash Key: depname
+                     Hash Module: 3
+                     ->  Parallel Seq Scan on empsalary
+ Optimizer: Postgres query optimizer
+(11 rows)
+
+SELECT sum(salary) OVER w, rank() OVER w FROM empsalary WINDOW w AS (PARTITION 
BY depname ORDER BY salary DESC);
+  sum  | rank 
+-------+------
+  3900 |    1
+  7400 |    2
+  5000 |    1
+ 14600 |    2
+ 14600 |    2
+  6000 |    1
+ 16400 |    2
+ 16400 |    2
+ 20900 |    4
+ 25100 |    5
+(10 rows)
+
+-- w8
+-- strict aggs
+set enable_parallel = off;
+EXPLAIN(COSTS OFF)
+SELECT empno, depname, salary, bonus, depadj, MIN(bonus) OVER (ORDER BY 
empno), MAX(depadj) OVER () FROM(
+       SELECT *,
+               CASE WHEN enroll_date < '2008-01-01' THEN 2008 - extract(YEAR 
FROM enroll_date) END * 500 AS bonus,
+               CASE WHEN
+                       AVG(salary) OVER (PARTITION BY depname) < salary
+               THEN 200 END AS depadj FROM empsalary
+)s;
+                            QUERY PLAN                             
+-------------------------------------------------------------------
+ WindowAgg
+   ->  WindowAgg
+         Order By: s.empno
+         ->  Gather Motion 3:1  (slice1; segments: 3)
+               Merge Key: s.empno
+               ->  Sort
+                     Sort Key: s.empno
+                     ->  Subquery Scan on s
+                           ->  WindowAgg
+                                 Partition By: empsalary.depname
+                                 ->  Sort
+                                       Sort Key: empsalary.depname
+                                       ->  Seq Scan on empsalary
+ Optimizer: Postgres query optimizer
+(14 rows)
+
+SELECT empno, depname, salary, bonus, depadj, MIN(bonus) OVER (ORDER BY 
empno), MAX(depadj) OVER () FROM(
+       SELECT *,
+               CASE WHEN enroll_date < '2008-01-01' THEN 2008 - extract(YEAR 
FROM enroll_date) END * 500 AS bonus,
+               CASE WHEN
+                       AVG(salary) OVER (PARTITION BY depname) < salary
+               THEN 200 END AS depadj FROM empsalary
+)s;
+ empno |  depname  | salary | bonus | depadj | min  | max 
+-------+-----------+--------+-------+--------+------+-----
+     1 | sales     |   5000 |  1000 |    200 | 1000 | 200
+     2 | personnel |   3900 |  1000 |    200 | 1000 | 200
+     3 | sales     |   4800 |   500 |        |  500 | 200
+     4 | sales     |   4800 |   500 |        |  500 | 200
+     5 | personnel |   3500 |   500 |        |  500 | 200
+     7 | develop   |   4200 |       |        |  500 | 200
+     8 | develop   |   6000 |  1000 |    200 |  500 | 200
+     9 | develop   |   4500 |       |        |  500 | 200
+    10 | develop   |   5200 |   500 |    200 |  500 | 200
+    11 | develop   |   5200 |   500 |    200 |  500 | 200
+(10 rows)
+
+set enable_parallel = on;
+EXPLAIN(COSTS OFF)
+SELECT empno, depname, salary, bonus, depadj, MIN(bonus) OVER (ORDER BY 
empno), MAX(depadj) OVER () FROM(
+       SELECT *,
+               CASE WHEN enroll_date < '2008-01-01' THEN 2008 - extract(YEAR 
FROM enroll_date) END * 500 AS bonus,
+               CASE WHEN
+                       AVG(salary) OVER (PARTITION BY depname) < salary
+               THEN 200 END AS depadj FROM empsalary
+)s;
+                            QUERY PLAN                             
+-------------------------------------------------------------------
+ WindowAgg
+   ->  WindowAgg
+         Order By: s.empno
+         ->  Gather Motion 3:1  (slice1; segments: 3)
+               Merge Key: s.empno
+               ->  Sort
+                     Sort Key: s.empno
+                     ->  Subquery Scan on s
+                           ->  WindowAgg
+                                 Partition By: empsalary.depname
+                                 ->  Sort
+                                       Sort Key: empsalary.depname
+                                       ->  Seq Scan on empsalary
+ Optimizer: Postgres query optimizer
+(14 rows)
+
+SELECT empno, depname, salary, bonus, depadj, MIN(bonus) OVER (ORDER BY 
empno), MAX(depadj) OVER () FROM(
+       SELECT *,
+               CASE WHEN enroll_date < '2008-01-01' THEN 2008 - extract(YEAR 
FROM enroll_date) END * 500 AS bonus,
+               CASE WHEN
+                       AVG(salary) OVER (PARTITION BY depname) < salary
+               THEN 200 END AS depadj FROM empsalary
+)s;
+ empno |  depname  | salary | bonus | depadj | min  | max 
+-------+-----------+--------+-------+--------+------+-----
+     1 | sales     |   5000 |  1000 |    200 | 1000 | 200
+     2 | personnel |   3900 |  1000 |    200 | 1000 | 200
+     3 | sales     |   4800 |   500 |        |  500 | 200
+     4 | sales     |   4800 |   500 |        |  500 | 200
+     5 | personnel |   3500 |   500 |        |  500 | 200
+     7 | develop   |   4200 |       |        |  500 | 200
+     8 | develop   |   6000 |  1000 |    200 |  500 | 200
+     9 | develop   |   4500 |       |        |  500 | 200
+    10 | develop   |   5200 |   500 |    200 |  500 | 200
+    11 | develop   |   5200 |   500 |    200 |  500 | 200
+(10 rows)
+
+-- w9
+set enable_parallel = off;
+EXPLAIN(COSTS OFF)
+select sum(salary) over (order by enroll_date range between '1 year'::interval 
preceding and '1 year'::interval following),
+       salary, enroll_date from empsalary;
+                   QUERY PLAN                   
+------------------------------------------------
+ WindowAgg
+   Order By: enroll_date
+   ->  Gather Motion 3:1  (slice1; segments: 3)
+         Merge Key: enroll_date
+         ->  Sort
+               Sort Key: enroll_date
+               ->  Seq Scan on empsalary
+ Optimizer: Postgres query optimizer
+(8 rows)
+
+select sum(salary) over (order by enroll_date range between '1 year'::interval 
preceding and '1 year'::interval following),
+       salary, enroll_date from empsalary;
+  sum  | salary | enroll_date 
+-------+--------+-------------
+ 34900 |   5000 | 10-01-2006
+ 34900 |   6000 | 10-01-2006
+ 38400 |   3900 | 12-23-2006
+ 47100 |   4800 | 08-01-2007
+ 47100 |   5200 | 08-01-2007
+ 47100 |   4800 | 08-08-2007
+ 47100 |   5200 | 08-15-2007
+ 36100 |   3500 | 12-10-2007
+ 32200 |   4500 | 01-01-2008
+ 32200 |   4200 | 01-01-2008
+(10 rows)
+
+set enable_parallel = on;
+EXPLAIN(COSTS OFF)
+select sum(salary) over (order by enroll_date range between '1 year'::interval 
preceding and '1 year'::interval following),
+       salary, enroll_date from empsalary;
+                    QUERY PLAN                    
+--------------------------------------------------
+ WindowAgg
+   Order By: enroll_date
+   ->  Gather Motion 6:1  (slice1; segments: 6)
+         Merge Key: enroll_date
+         ->  Sort
+               Sort Key: enroll_date
+               ->  Parallel Seq Scan on empsalary
+ Optimizer: Postgres query optimizer
+(8 rows)
+
+select sum(salary) over (order by enroll_date range between '1 year'::interval 
preceding and '1 year'::interval following),
+       salary, enroll_date from empsalary;
+  sum  | salary | enroll_date 
+-------+--------+-------------
+ 34900 |   5000 | 10-01-2006
+ 34900 |   6000 | 10-01-2006
+ 38400 |   3900 | 12-23-2006
+ 47100 |   4800 | 08-01-2007
+ 47100 |   5200 | 08-01-2007
+ 47100 |   4800 | 08-08-2007
+ 47100 |   5200 | 08-15-2007
+ 36100 |   3500 | 12-10-2007
+ 32200 |   4500 | 01-01-2008
+ 32200 |   4200 | 01-01-2008
+(10 rows)
+
+-- w10 
+set enable_parallel = off;
+EXPLAIN(COSTS OFF)
+select sum(salary) over (order by enroll_date desc range between '1 
year'::interval preceding and '1 year'::interval following),
+       salary, enroll_date from empsalary;
+                   QUERY PLAN                   
+------------------------------------------------
+ WindowAgg
+   Order By: enroll_date
+   ->  Gather Motion 3:1  (slice1; segments: 3)
+         Merge Key: enroll_date
+         ->  Sort
+               Sort Key: enroll_date DESC
+               ->  Seq Scan on empsalary
+ Optimizer: Postgres query optimizer
+(8 rows)
+
+select sum(salary) over (order by enroll_date desc range between '1 
year'::interval preceding and '1 year'::interval following),
+       salary, enroll_date from empsalary;
+  sum  | salary | enroll_date 
+-------+--------+-------------
+ 32200 |   4200 | 01-01-2008
+ 32200 |   4500 | 01-01-2008
+ 36100 |   3500 | 12-10-2007
+ 47100 |   5200 | 08-15-2007
+ 47100 |   4800 | 08-08-2007
+ 47100 |   4800 | 08-01-2007
+ 47100 |   5200 | 08-01-2007
+ 38400 |   3900 | 12-23-2006
+ 34900 |   5000 | 10-01-2006
+ 34900 |   6000 | 10-01-2006
+(10 rows)
+
+set enable_parallel = on;
+EXPLAIN(COSTS OFF)
+select sum(salary) over (order by enroll_date desc range between '1 
year'::interval preceding and '1 year'::interval following),
+       salary, enroll_date from empsalary;
+                    QUERY PLAN                    
+--------------------------------------------------
+ WindowAgg
+   Order By: enroll_date
+   ->  Gather Motion 6:1  (slice1; segments: 6)
+         Merge Key: enroll_date
+         ->  Sort
+               Sort Key: enroll_date DESC
+               ->  Parallel Seq Scan on empsalary
+ Optimizer: Postgres query optimizer
+(8 rows)
+
+select sum(salary) over (order by enroll_date desc range between '1 
year'::interval preceding and '1 year'::interval following),
+       salary, enroll_date from empsalary;
+  sum  | salary | enroll_date 
+-------+--------+-------------
+ 32200 |   4200 | 01-01-2008
+ 32200 |   4500 | 01-01-2008
+ 36100 |   3500 | 12-10-2007
+ 47100 |   5200 | 08-15-2007
+ 47100 |   4800 | 08-08-2007
+ 47100 |   4800 | 08-01-2007
+ 47100 |   5200 | 08-01-2007
+ 38400 |   3900 | 12-23-2006
+ 34900 |   5000 | 10-01-2006
+ 34900 |   6000 | 10-01-2006
+(10 rows)
+
+-- w11
+set enable_parallel = off;
+EXPLAIN(COSTS OFF)
+select sum(salary) over (order by enroll_date desc range between '1 
year'::interval following and '1 year'::interval following),
+       salary, enroll_date from empsalary;
+                   QUERY PLAN                   
+------------------------------------------------
+ WindowAgg
+   Order By: enroll_date
+   ->  Gather Motion 3:1  (slice1; segments: 3)
+         Merge Key: enroll_date
+         ->  Sort
+               Sort Key: enroll_date DESC
+               ->  Seq Scan on empsalary
+ Optimizer: Postgres query optimizer
+(8 rows)
+
+select sum(salary) over (order by enroll_date desc range between '1 
year'::interval following and '1 year'::interval following),
+       salary, enroll_date from empsalary;
+ sum | salary | enroll_date 
+-----+--------+-------------
+     |   4200 | 01-01-2008
+     |   4500 | 01-01-2008
+     |   3500 | 12-10-2007
+     |   5200 | 08-15-2007
+     |   4800 | 08-08-2007
+     |   4800 | 08-01-2007
+     |   5200 | 08-01-2007
+     |   3900 | 12-23-2006
+     |   5000 | 10-01-2006
+     |   6000 | 10-01-2006
+(10 rows)
+
+set enable_parallel = on;
+EXPLAIN(COSTS OFF)
+select sum(salary) over (order by enroll_date desc range between '1 
year'::interval following and '1 year'::interval following),
+       salary, enroll_date from empsalary;
+                    QUERY PLAN                    
+--------------------------------------------------
+ WindowAgg
+   Order By: enroll_date
+   ->  Gather Motion 6:1  (slice1; segments: 6)
+         Merge Key: enroll_date
+         ->  Sort
+               Sort Key: enroll_date DESC
+               ->  Parallel Seq Scan on empsalary
+ Optimizer: Postgres query optimizer
+(8 rows)
+
+select sum(salary) over (order by enroll_date desc range between '1 
year'::interval following and '1 year'::interval following),
+       salary, enroll_date from empsalary;
+ sum | salary | enroll_date 
+-----+--------+-------------
+     |   4200 | 01-01-2008
+     |   4500 | 01-01-2008
+     |   3500 | 12-10-2007
+     |   5200 | 08-15-2007
+     |   4800 | 08-08-2007
+     |   4800 | 08-01-2007
+     |   5200 | 08-01-2007
+     |   3900 | 12-23-2006
+     |   5000 | 10-01-2006
+     |   6000 | 10-01-2006
+(10 rows)
+
+-- w12
+set enable_parallel = off;
+EXPLAIN(COSTS OFF)
+select sum(salary) over (order by enroll_date range between '1 year'::interval 
preceding and '1 year'::interval following
+       exclude current row), salary, enroll_date from empsalary;
+                   QUERY PLAN                   
+------------------------------------------------
+ WindowAgg
+   Order By: enroll_date
+   ->  Gather Motion 3:1  (slice1; segments: 3)
+         Merge Key: enroll_date
+         ->  Sort
+               Sort Key: enroll_date
+               ->  Seq Scan on empsalary
+ Optimizer: Postgres query optimizer
+(8 rows)
+
+select sum(salary) over (order by enroll_date range between '1 year'::interval 
preceding and '1 year'::interval following
+       exclude current row), salary, enroll_date from empsalary;
+  sum  | salary | enroll_date 
+-------+--------+-------------
+ 29900 |   5000 | 10-01-2006
+ 28900 |   6000 | 10-01-2006
+ 34500 |   3900 | 12-23-2006
+ 42300 |   4800 | 08-01-2007
+ 41900 |   5200 | 08-01-2007
+ 42300 |   4800 | 08-08-2007
+ 41900 |   5200 | 08-15-2007
+ 32600 |   3500 | 12-10-2007
+ 27700 |   4500 | 01-01-2008
+ 28000 |   4200 | 01-01-2008
+(10 rows)
+
+set enable_parallel = on;
+EXPLAIN(COSTS OFF)
+select sum(salary) over (order by enroll_date range between '1 year'::interval 
preceding and '1 year'::interval following
+       exclude current row), salary, enroll_date from empsalary;
+                    QUERY PLAN                    
+--------------------------------------------------
+ WindowAgg
+   Order By: enroll_date
+   ->  Gather Motion 6:1  (slice1; segments: 6)
+         Merge Key: enroll_date
+         ->  Sort
+               Sort Key: enroll_date
+               ->  Parallel Seq Scan on empsalary
+ Optimizer: Postgres query optimizer
+(8 rows)
+
+select sum(salary) over (order by enroll_date range between '1 year'::interval 
preceding and '1 year'::interval following
+       exclude current row), salary, enroll_date from empsalary;
+  sum  | salary | enroll_date 
+-------+--------+-------------
+ 29900 |   5000 | 10-01-2006
+ 28900 |   6000 | 10-01-2006
+ 34500 |   3900 | 12-23-2006
+ 42300 |   4800 | 08-01-2007
+ 41900 |   5200 | 08-01-2007
+ 42300 |   4800 | 08-08-2007
+ 41900 |   5200 | 08-15-2007
+ 32600 |   3500 | 12-10-2007
+ 27700 |   4500 | 01-01-2008
+ 28000 |   4200 | 01-01-2008
+(10 rows)
+
+--
+-- End of test of Parallel process of Window Functions.
+--
+-- start_ignore
+drop schema window_parallel cascade;
+NOTICE:  drop cascades to table empsalary
+-- end_ignore
+reset min_parallel_table_scan_size;
+reset enable_parallel;
+reset gp_appendonly_insert_files;
+reset force_parallel_mode;
+reset optimizer;
diff --git a/src/test/regress/greenplum_schedule 
b/src/test/regress/greenplum_schedule
index 3614e349ff8..f2f66e6cd6e 100755
--- a/src/test/regress/greenplum_schedule
+++ b/src/test/regress/greenplum_schedule
@@ -281,6 +281,9 @@ test: freeze_aux_tables
 # cbdb parallel test
 test: cbdb_parallel
 
+# window function parallel test
+test: window_parallel
+
 # These cannot run in parallel, because they check that VACUUM FULL shrinks 
table size.
 # A concurrent session could hold back the xid horizon and prevent old tuples 
from being
 # removed.
diff --git a/src/test/regress/sql/cluster.sql b/src/test/regress/sql/cluster.sql
index 5eb71740fd2..61cf6a4e6cf 100644
--- a/src/test/regress/sql/cluster.sql
+++ b/src/test/regress/sql/cluster.sql
@@ -226,9 +226,9 @@ set enable_indexscan = off;
 set maintenance_work_mem = '1MB';
 cluster clstr_4 using cluster_sort;
 select * from
-(select hundred, lag(hundred) over () as lhundred,
-        thousand, lag(thousand) over () as lthousand,
-        tenthous, lag(tenthous) over () as ltenthous from clstr_4) ss
+(select hundred, lag(hundred) over (order by hundred) as lhundred,
+        thousand, lag(thousand) over (order by hundred) as lthousand,
+        tenthous, lag(tenthous) over (order by hundred) as ltenthous from 
clstr_4) ss
 where row(hundred, thousand, tenthous) <= row(lhundred, lthousand, ltenthous);
 
 reset enable_indexscan;
diff --git a/src/test/regress/sql/select_parallel.sql 
b/src/test/regress/sql/select_parallel.sql
index 8a56061710e..846066fad05 100644
--- a/src/test/regress/sql/select_parallel.sql
+++ b/src/test/regress/sql/select_parallel.sql
@@ -389,6 +389,7 @@ reset force_parallel_mode;
 reset role;
 
 -- Window function calculation can't be pushed to workers.
+-- CBDB_PARALLEL: window function's subpath could be parallel.
 explain (costs off, verbose)
   select count(*) from tenk1 a where (unique1, two) in
     (select unique1, row_number() over() from tenk1 b);
diff --git a/src/test/regress/sql/statement_mem_for_windowagg.sql 
b/src/test/regress/sql/statement_mem_for_windowagg.sql
index 5c4b96a1761..a471690c6be 100644
--- a/src/test/regress/sql/statement_mem_for_windowagg.sql
+++ b/src/test/regress/sql/statement_mem_for_windowagg.sql
@@ -2,6 +2,7 @@ CREATE TABLE dummy_table(x int, y int) DISTRIBUTED BY (y);
 INSERT INTO dummy_table SELECT generate_series(0, 20000), 0;
 INSERT INTO dummy_table SELECT generate_series(0, 20000), 3;
 INSERT INTO dummy_table SELECT generate_series(0, 20000), 10;
+set enable_parallel = off; 
 
 -- 1. Test that if we set statement_mem to a larger value, the tuplestore
 -- for caching the tuples in partition used in WindowAgg is able to be fitted
@@ -53,5 +54,6 @@ SELECT 
gp_inject_fault_infinite('distinct_winagg_perform_sort', 'reset', dbid)
   FROM gp_segment_configuration WHERE role='p' AND content>=0;
 
 -- Do some clean-ups.
+reset enable_parallel;
 DROP TABLE dummy_table;
 RESET statement_mem;
diff --git a/src/test/regress/sql/window.sql b/src/test/regress/sql/window.sql
index 70dd94fafae..1ae2af61983 100644
--- a/src/test/regress/sql/window.sql
+++ b/src/test/regress/sql/window.sql
@@ -242,63 +242,63 @@ SELECT sum(unique1) over (order by four range between 
current row and unbounded
 FROM tenk1 WHERE unique1 < 10;
 
 set search_path=singleseg, public;
-SELECT sum(unique1) over (rows between current row and unbounded following),
+SELECT sum(unique1) over (order by unique1 rows between current row and 
unbounded following),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
 
-SELECT sum(unique1) over (rows between 2 preceding and 2 following),
+SELECT sum(unique1) over (order by unique1 rows between 2 preceding and 2 
following),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
 
-SELECT sum(unique1) over (rows between 2 preceding and 2 following exclude no 
others),
+SELECT sum(unique1) over (order by unique1 rows between 2 preceding and 2 
following exclude no others),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
 
-SELECT sum(unique1) over (rows between 2 preceding and 2 following exclude 
current row),
+SELECT sum(unique1) over (order by unique1 rows between 2 preceding and 2 
following exclude current row),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
 
-SELECT sum(unique1) over (rows between 2 preceding and 2 following exclude 
group),
+SELECT sum(unique1) over (order by unique1 rows between 2 preceding and 2 
following exclude group),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
 
-SELECT sum(unique1) over (rows between 2 preceding and 2 following exclude 
ties),
+SELECT sum(unique1) over (order by unique1 rows between 2 preceding and 2 
following exclude ties),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
 
-SELECT first_value(unique1) over (ORDER BY four rows between current row and 2 
following exclude current row),
+SELECT first_value(unique1) over (ORDER BY four, unique1 rows between current 
row and 2 following exclude current row),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
 
-SELECT first_value(unique1) over (ORDER BY four rows between current row and 2 
following exclude group),
+SELECT first_value(unique1) over (ORDER BY four, unique1 rows between current 
row and 2 following exclude group),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
 
-SELECT first_value(unique1) over (ORDER BY four rows between current row and 2 
following exclude ties),
+SELECT first_value(unique1) over (ORDER BY four, unique1 rows between current 
row and 2 following exclude ties),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
 
-SELECT last_value(unique1) over (ORDER BY four rows between current row and 2 
following exclude current row),
+SELECT last_value(unique1) over (ORDER BY four, unique1 rows between current 
row and 2 following exclude current row),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
 
-SELECT last_value(unique1) over (ORDER BY four rows between current row and 2 
following exclude group),
+SELECT last_value(unique1) over (ORDER BY four, unique1 rows between current 
row and 2 following exclude group),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
 
-SELECT last_value(unique1) over (ORDER BY four rows between current row and 2 
following exclude ties),
+SELECT last_value(unique1) over (ORDER BY four, unique1 rows between current 
row and 2 following exclude ties),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
 
-SELECT sum(unique1) over (rows between 2 preceding and 1 preceding),
+SELECT sum(unique1) over (order by unique1 rows between 2 preceding and 1 
preceding),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
 
-SELECT sum(unique1) over (rows between 1 following and 3 following),
+SELECT sum(unique1) over (order by unique1 rows between 1 following and 3 
following),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
 
-SELECT sum(unique1) over (rows between unbounded preceding and 1 following),
+SELECT sum(unique1) over (order by unique1 rows between unbounded preceding 
and 1 following),
        unique1, four
 FROM tenk1 WHERE unique1 < 10;
 
@@ -322,7 +322,7 @@ SELECT first_value(unique1) over w,
        nth_value(unique1, 2) over w AS nth_2,
        last_value(unique1) over w, unique1, four
 FROM tenk1 WHERE unique1 < 10
-WINDOW w AS (order by four range between current row and unbounded following);
+WINDOW w AS (order by unique1, four range between current row and unbounded 
following);
 
 SELECT sum(unique1) over
        (order by unique1
diff --git a/src/test/regress/sql/window_parallel.sql 
b/src/test/regress/sql/window_parallel.sql
new file mode 100644
index 00000000000..e8136750b2a
--- /dev/null
+++ b/src/test/regress/sql/window_parallel.sql
@@ -0,0 +1,223 @@
+set force_parallel_mode = 0;
+set optimizer = off;
+
+create schema window_parallel;
+set search_path to window_parallel;
+set gp_appendonly_insert_files = 4;
+set min_parallel_table_scan_size = 0;
+
+--
+-- Test of Parallel process of Window Functions.
+--
+CREATE TABLE empsalary (
+    depname varchar,
+    empno bigint,
+    salary int,
+    enroll_date date
+);
+
+INSERT INTO empsalary VALUES
+('develop', 10, 5200, '2007-08-01'),
+('sales', 1, 5000, '2006-10-01'),
+('personnel', 5, 3500, '2007-12-10'),
+('sales', 4, 4800, '2007-08-08'),
+('personnel', 2, 3900, '2006-12-23'),
+('develop', 7, 4200, '2008-01-01'),
+('develop', 9, 4500, '2008-01-01'),
+('sales', 3, 4800, '2007-08-01'),
+('develop', 8, 6000, '2006-10-01'),
+('develop', 11, 5200, '2007-08-15');
+
+
+-- w1
+set enable_parallel = off;
+EXPLAIN(COSTS OFF)
+SELECT depname, empno, salary, sum(salary) OVER (PARTITION BY depname) FROM 
empsalary ORDER BY depname, salary;
+SELECT depname, empno, salary, sum(salary) OVER (PARTITION BY depname) FROM 
empsalary ORDER BY depname, salary;
+set enable_parallel = on;
+EXPLAIN(COSTS OFF)
+SELECT depname, empno, salary, sum(salary) OVER (PARTITION BY depname) FROM 
empsalary ORDER BY depname, salary;
+SELECT depname, empno, salary, sum(salary) OVER (PARTITION BY depname) FROM 
empsalary ORDER BY depname, salary;
+
+-- w2
+set enable_parallel = off;
+EXPLAIN(COSTS OFF)
+SELECT depname, empno, salary, rank() OVER (PARTITION BY depname ORDER BY 
salary) FROM empsalary;
+SELECT depname, empno, salary, rank() OVER (PARTITION BY depname ORDER BY 
salary) FROM empsalary;
+set enable_parallel = on;
+EXPLAIN(COSTS OFF)
+SELECT depname, empno, salary, rank() OVER (PARTITION BY depname ORDER BY 
salary) FROM empsalary;
+SELECT depname, empno, salary, rank() OVER (PARTITION BY depname ORDER BY 
salary) FROM empsalary;
+
+-- w3
+set enable_parallel = off;
+EXPLAIN(COSTS OFF)
+SELECT depname, empno, salary, sum(salary) OVER w FROM empsalary WINDOW w AS 
(PARTITION BY depname);
+SELECT depname, empno, salary, sum(salary) OVER w FROM empsalary WINDOW w AS 
(PARTITION BY depname);
+set enable_parallel = on;
+EXPLAIN(COSTS OFF)
+SELECT depname, empno, salary, sum(salary) OVER w FROM empsalary WINDOW w AS 
(PARTITION BY depname);
+SELECT depname, empno, salary, sum(salary) OVER w FROM empsalary WINDOW w AS 
(PARTITION BY depname);
+
+-- w4
+set enable_parallel = off;
+EXPLAIN(COSTS OFF)
+SELECT depname, empno, salary, rank() OVER w FROM empsalary WINDOW w AS 
(PARTITION BY depname ORDER BY salary) ORDER BY rank() OVER w;
+SELECT depname, empno, salary, rank() OVER w FROM empsalary WINDOW w AS 
(PARTITION BY depname ORDER BY salary) ORDER BY rank() OVER w;
+set enable_parallel = on;
+EXPLAIN(COSTS OFF)
+SELECT depname, empno, salary, rank() OVER w FROM empsalary WINDOW w AS 
(PARTITION BY depname ORDER BY salary) ORDER BY rank() OVER w;
+SELECT depname, empno, salary, rank() OVER w FROM empsalary WINDOW w AS 
(PARTITION BY depname ORDER BY salary) ORDER BY rank() OVER w;
+
+-- w5
+set enable_parallel = off;
+EXPLAIN(COSTS OFF)
+SELECT sum(salary),
+       row_number() OVER (ORDER BY depname),
+       sum(sum(salary)) OVER (ORDER BY depname DESC)
+FROM empsalary GROUP BY depname;
+SELECT sum(salary),
+       row_number() OVER (ORDER BY depname),
+       sum(sum(salary)) OVER (ORDER BY depname DESC)
+FROM empsalary GROUP BY depname;
+set enable_parallel = on;
+EXPLAIN(COSTS OFF)
+SELECT sum(salary),
+       row_number() OVER (ORDER BY depname),
+       sum(sum(salary)) OVER (ORDER BY depname DESC)
+FROM empsalary GROUP BY depname;
+SELECT sum(salary),
+       row_number() OVER (ORDER BY depname),
+       sum(sum(salary)) OVER (ORDER BY depname DESC)
+FROM empsalary GROUP BY depname;
+
+
+-- w6
+set enable_parallel = off;
+EXPLAIN(COSTS OFF)
+-- identical windows with different names
+SELECT sum(salary) OVER w1, count(*) OVER w2
+FROM empsalary WINDOW w1 AS (ORDER BY salary), w2 AS (ORDER BY salary);
+SELECT sum(salary) OVER w1, count(*) OVER w2
+FROM empsalary WINDOW w1 AS (ORDER BY salary), w2 AS (ORDER BY salary);
+set enable_parallel = on;
+EXPLAIN(COSTS OFF)
+-- identical windows with different names
+SELECT sum(salary) OVER w1, count(*) OVER w2
+FROM empsalary WINDOW w1 AS (ORDER BY salary), w2 AS (ORDER BY salary);
+SELECT sum(salary) OVER w1, count(*) OVER w2
+FROM empsalary WINDOW w1 AS (ORDER BY salary), w2 AS (ORDER BY salary);
+
+-- w7
+-- mixture of agg/wfunc in the same window
+set enable_parallel = off;
+EXPLAIN(COSTS OFF)
+SELECT sum(salary) OVER w, rank() OVER w FROM empsalary WINDOW w AS (PARTITION 
BY depname ORDER BY salary DESC);
+SELECT sum(salary) OVER w, rank() OVER w FROM empsalary WINDOW w AS (PARTITION 
BY depname ORDER BY salary DESC);
+set enable_parallel = on;
+EXPLAIN(COSTS OFF)
+SELECT sum(salary) OVER w, rank() OVER w FROM empsalary WINDOW w AS (PARTITION 
BY depname ORDER BY salary DESC);
+SELECT sum(salary) OVER w, rank() OVER w FROM empsalary WINDOW w AS (PARTITION 
BY depname ORDER BY salary DESC);
+
+-- w8
+-- strict aggs
+set enable_parallel = off;
+EXPLAIN(COSTS OFF)
+SELECT empno, depname, salary, bonus, depadj, MIN(bonus) OVER (ORDER BY 
empno), MAX(depadj) OVER () FROM(
+       SELECT *,
+               CASE WHEN enroll_date < '2008-01-01' THEN 2008 - extract(YEAR 
FROM enroll_date) END * 500 AS bonus,
+               CASE WHEN
+                       AVG(salary) OVER (PARTITION BY depname) < salary
+               THEN 200 END AS depadj FROM empsalary
+)s;
+SELECT empno, depname, salary, bonus, depadj, MIN(bonus) OVER (ORDER BY 
empno), MAX(depadj) OVER () FROM(
+       SELECT *,
+               CASE WHEN enroll_date < '2008-01-01' THEN 2008 - extract(YEAR 
FROM enroll_date) END * 500 AS bonus,
+               CASE WHEN
+                       AVG(salary) OVER (PARTITION BY depname) < salary
+               THEN 200 END AS depadj FROM empsalary
+)s;
+set enable_parallel = on;
+EXPLAIN(COSTS OFF)
+SELECT empno, depname, salary, bonus, depadj, MIN(bonus) OVER (ORDER BY 
empno), MAX(depadj) OVER () FROM(
+       SELECT *,
+               CASE WHEN enroll_date < '2008-01-01' THEN 2008 - extract(YEAR 
FROM enroll_date) END * 500 AS bonus,
+               CASE WHEN
+                       AVG(salary) OVER (PARTITION BY depname) < salary
+               THEN 200 END AS depadj FROM empsalary
+)s;
+SELECT empno, depname, salary, bonus, depadj, MIN(bonus) OVER (ORDER BY 
empno), MAX(depadj) OVER () FROM(
+       SELECT *,
+               CASE WHEN enroll_date < '2008-01-01' THEN 2008 - extract(YEAR 
FROM enroll_date) END * 500 AS bonus,
+               CASE WHEN
+                       AVG(salary) OVER (PARTITION BY depname) < salary
+               THEN 200 END AS depadj FROM empsalary
+)s;
+
+-- w9
+set enable_parallel = off;
+EXPLAIN(COSTS OFF)
+select sum(salary) over (order by enroll_date range between '1 year'::interval 
preceding and '1 year'::interval following),
+       salary, enroll_date from empsalary;
+select sum(salary) over (order by enroll_date range between '1 year'::interval 
preceding and '1 year'::interval following),
+       salary, enroll_date from empsalary;
+set enable_parallel = on;
+EXPLAIN(COSTS OFF)
+select sum(salary) over (order by enroll_date range between '1 year'::interval 
preceding and '1 year'::interval following),
+       salary, enroll_date from empsalary;
+select sum(salary) over (order by enroll_date range between '1 year'::interval 
preceding and '1 year'::interval following),
+       salary, enroll_date from empsalary;
+
+-- w10 
+set enable_parallel = off;
+EXPLAIN(COSTS OFF)
+select sum(salary) over (order by enroll_date desc range between '1 
year'::interval preceding and '1 year'::interval following),
+       salary, enroll_date from empsalary;
+select sum(salary) over (order by enroll_date desc range between '1 
year'::interval preceding and '1 year'::interval following),
+       salary, enroll_date from empsalary;
+set enable_parallel = on;
+EXPLAIN(COSTS OFF)
+select sum(salary) over (order by enroll_date desc range between '1 
year'::interval preceding and '1 year'::interval following),
+       salary, enroll_date from empsalary;
+select sum(salary) over (order by enroll_date desc range between '1 
year'::interval preceding and '1 year'::interval following),
+       salary, enroll_date from empsalary;
+
+-- w11
+set enable_parallel = off;
+EXPLAIN(COSTS OFF)
+select sum(salary) over (order by enroll_date desc range between '1 
year'::interval following and '1 year'::interval following),
+       salary, enroll_date from empsalary;
+select sum(salary) over (order by enroll_date desc range between '1 
year'::interval following and '1 year'::interval following),
+       salary, enroll_date from empsalary;
+set enable_parallel = on;
+EXPLAIN(COSTS OFF)
+select sum(salary) over (order by enroll_date desc range between '1 
year'::interval following and '1 year'::interval following),
+       salary, enroll_date from empsalary;
+select sum(salary) over (order by enroll_date desc range between '1 
year'::interval following and '1 year'::interval following),
+       salary, enroll_date from empsalary;
+
+-- w12
+set enable_parallel = off;
+EXPLAIN(COSTS OFF)
+select sum(salary) over (order by enroll_date range between '1 year'::interval 
preceding and '1 year'::interval following
+       exclude current row), salary, enroll_date from empsalary;
+select sum(salary) over (order by enroll_date range between '1 year'::interval 
preceding and '1 year'::interval following
+       exclude current row), salary, enroll_date from empsalary;
+set enable_parallel = on;
+EXPLAIN(COSTS OFF)
+select sum(salary) over (order by enroll_date range between '1 year'::interval 
preceding and '1 year'::interval following
+       exclude current row), salary, enroll_date from empsalary;
+select sum(salary) over (order by enroll_date range between '1 year'::interval 
preceding and '1 year'::interval following
+       exclude current row), salary, enroll_date from empsalary;
+
+--
+-- End of test of Parallel process of Window Functions.
+--
+-- start_ignore
+drop schema window_parallel cascade;
+-- end_ignore
+reset min_parallel_table_scan_size;
+reset enable_parallel;
+reset gp_appendonly_insert_files;
+reset force_parallel_mode;
+reset optimizer;
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to