================================================================================
Window Functions Partition by
================================================================================

SELECT
  x,
  y,
  z,
  AVG(x) OVER (PARTITION BY y)
FROM tab1;

--------------------------------------------------------------------------------

(program
  (statement
    (select
      (keyword_select)
      (select_expression
        (term
          value: (field
            name: (identifier)))
        (term
          value: (field
            name: (identifier)))
        (term
          value: (field
            name: (identifier)))
        (term
          value: (window_function
            (invocation
              (object_reference
                name: (identifier))
              parameter: (term
                value: (field
                  name: (identifier))))
            (keyword_over)
            (window_specification
              (partition_by
                (keyword_partition)
                (keyword_by)
                (field
                  name: (identifier))))))))
    (from
      (keyword_from)
      (relation
        (object_reference
          name: (identifier))))))

================================================================================
Window Functions Order by
================================================================================

SELECT
  x,
  y,
  z,
  AVG(x) OVER (ORDER BY y DESC NULLS LAST)
FROM tab1;

--------------------------------------------------------------------------------

(program
  (statement
    (select
      (keyword_select)
      (select_expression
        (term
          value: (field
            name: (identifier)))
        (term
          value: (field
            name: (identifier)))
        (term
          value: (field
            name: (identifier)))
        (term
          value: (window_function
            (invocation
              (object_reference
                name: (identifier))
              parameter: (term
                value: (field
                  name: (identifier))))
            (keyword_over)
            (window_specification
              (order_by
                (keyword_order)
                (keyword_by)
                (order_target
                  (field
                    name: (identifier))
                  (direction
                    (keyword_desc))
                  (keyword_nulls)
                  (keyword_last))))))))
    (from
      (keyword_from)
      (relation
        (object_reference
          name: (identifier))))))

================================================================================
Window Functions Partition and Order by
================================================================================

SELECT
  x,
  y,
  z,
  AVG(x) OVER (PARTITION BY z ORDER BY y DESC NULLS FIRST)
FROM tab1;

--------------------------------------------------------------------------------

(program
  (statement
    (select
      (keyword_select)
      (select_expression
        (term
          value: (field
            name: (identifier)))
        (term
          value: (field
            name: (identifier)))
        (term
          value: (field
            name: (identifier)))
        (term
          value: (window_function
            (invocation
              (object_reference
                name: (identifier))
              parameter: (term
                value: (field
                  name: (identifier))))
            (keyword_over)
            (window_specification
              (partition_by
                (keyword_partition)
                (keyword_by)
                (field
                  name: (identifier)))
              (order_by
                (keyword_order)
                (keyword_by)
                (order_target
                  (field
                    name: (identifier))
                  (direction
                    (keyword_desc))
                  (keyword_nulls)
                  (keyword_first))))))))
    (from
      (keyword_from)
      (relation
        (object_reference
          name: (identifier))))))

================================================================================
Window Functions Empty Window
================================================================================

SELECT
  a,
  SUM(b) OVER () AS empty_sum
FROM tab1;

--------------------------------------------------------------------------------

(program
  (statement
    (select
      (keyword_select)
      (select_expression
        (term
          value: (field
            name: (identifier)))
        (term
          value: (window_function
            (invocation
              (object_reference
                name: (identifier))
              parameter: (term
                value: (field
                  name: (identifier))))
            (keyword_over)
            (window_specification))
          (keyword_as)
          alias: (identifier))))
    (from
      (keyword_from)
      (relation
        (object_reference
          name: (identifier))))))

================================================================================
Window Functions two inline functions
================================================================================

SELECT
  a,
  SUM(b) OVER (PARTITION BY c) AS w1,
  AVG(b) OVER (ORDER BY d) AS w2,
FROM tab1;

--------------------------------------------------------------------------------

(program
  (statement
    (select
      (keyword_select)
      (select_expression
        (term
          value: (field
            name: (identifier)))
        (term
          value: (window_function
            (invocation
              (object_reference
                name: (identifier))
              parameter: (term
                value: (field
                  name: (identifier))))
            (keyword_over)
            (window_specification
              (partition_by
                (keyword_partition)
                (keyword_by)
                (field
                  name: (identifier)))))
          (keyword_as)
          alias: (identifier))
        (term
          value: (window_function
            (invocation
              (object_reference
                name: (identifier))
              parameter: (term
                value: (field
                  name: (identifier))))
            (keyword_over)
            (window_specification
              (order_by
                (keyword_order)
                (keyword_by)
                (order_target
                  (field
                    name: (identifier))))))
          (keyword_as)
          alias: (identifier))
        (term
          value: (field
            name: (identifier))
          alias: (identifier))))))

================================================================================
Window Functions separate definition
================================================================================

SELECT
  x,
  y,
  MAX(x) OVER window_def
FROM tab1
WINDOW window_def AS (PARTITION BY y);

--------------------------------------------------------------------------------

(program
  (statement
    (select
      (keyword_select)
      (select_expression
        (term
          value: (field
            name: (identifier)))
        (term
          value: (field
            name: (identifier)))
        (term
          value: (window_function
            (invocation
              (object_reference
                name: (identifier))
              parameter: (term
                value: (field
                  name: (identifier))))
            (keyword_over)
            (identifier)))))
    (from
      (keyword_from)
      (relation
        (object_reference
          name: (identifier)))
      (window_clause
        (keyword_window)
        (identifier)
        (keyword_as)
        (window_specification
          (partition_by
            (keyword_partition)
            (keyword_by)
            (field
              name: (identifier))))))))

================================================================================
Window Functions one inlined one named
================================================================================

SELECT
  a,
  SUM(b) OVER (PARTITION BY c) AS w1,
  AVG(b) OVER win AS w2
FROM tab1
WINDOW win AS (ORDER BY d)
;

--------------------------------------------------------------------------------

(program
  (statement
    (select
      (keyword_select)
      (select_expression
        (term
          value: (field
            name: (identifier)))
        (term
          value: (window_function
            (invocation
              (object_reference
                name: (identifier))
              parameter: (term
                value: (field
                  name: (identifier))))
            (keyword_over)
            (window_specification
              (partition_by
                (keyword_partition)
                (keyword_by)
                (field
                  name: (identifier)))))
          (keyword_as)
          alias: (identifier))
        (term
          value: (window_function
            (invocation
              (object_reference
                name: (identifier))
              parameter: (term
                value: (field
                  name: (identifier))))
            (keyword_over)
            (identifier))
          (keyword_as)
          alias: (identifier))))
    (from
      (keyword_from)
      (relation
        (object_reference
          name: (identifier)))
      (window_clause
        (keyword_window)
        (identifier)
        (keyword_as)
        (window_specification
          (order_by
            (keyword_order)
            (keyword_by)
            (order_target
              (field
                name: (identifier)))))))))

================================================================================
Window Functions partition order frame
================================================================================

SELECT
    a,
    c,
    MAX(c) OVER (
        PARTITION BY a
        ORDER BY a
        RANGE BETWEEN UNBOUNDED PRECEDING
        AND UNBOUNDED FOLLOWING
    ),
    MAX(c) OVER (
        PARTITION BY a
        RANGE a + 1 PRECEDING
    )
FROM
    tab;

--------------------------------------------------------------------------------

(program
  (statement
    (select
      (keyword_select)
      (select_expression
        (term
          value: (field
            name: (identifier)))
        (term
          value: (field
            name: (identifier)))
        (term
          value: (window_function
            (invocation
              (object_reference
                name: (identifier))
              parameter: (term
                value: (field
                  name: (identifier))))
            (keyword_over)
            (window_specification
              (partition_by
                (keyword_partition)
                (keyword_by)
                (field
                  name: (identifier)))
              (order_by
                (keyword_order)
                (keyword_by)
                (order_target
                  (field
                    name: (identifier))))
              (window_frame
                (keyword_range)
                (keyword_between)
                (frame_definition
                  (keyword_unbounded)
                  (keyword_preceding))
                (keyword_and)
                (frame_definition
                  (keyword_unbounded)
                  (keyword_following))))))
        (term
          value: (window_function
            (invocation
              (object_reference
                name: (identifier))
              parameter: (term
                value: (field
                  name: (identifier))))
            (keyword_over)
            (window_specification
              (partition_by
                (keyword_partition)
                (keyword_by)
                (field
                  name: (identifier)))
              (window_frame
                (keyword_range)
                (frame_definition
                  start: (binary_expression
                    left: (field
                      name: (identifier))
                    right: (literal))
                  (keyword_preceding))))))))
    (from
      (keyword_from)
      (relation
        (object_reference
          name: (identifier))))))

================================================================================
Window Functions complex example
================================================================================

SELECT
    a,
    c,
    MAX(c) OVER (
        PARTITION BY a,b
        ORDER BY a ASC NULLS FIRST
        ROWS BETWEEN 3 PRECEDING
        AND 3 FOLLOWING EXCLUDE CURRENT ROW
    )
FROM
    tab;

--------------------------------------------------------------------------------

(program
  (statement
    (select
      (keyword_select)
      (select_expression
        (term
          value: (field
            name: (identifier)))
        (term
          value: (field
            name: (identifier)))
        (term
          value: (window_function
            (invocation
              (object_reference
                name: (identifier))
              parameter: (term
                value: (field
                  name: (identifier))))
            (keyword_over)
            (window_specification
              (partition_by
                (keyword_partition)
                (keyword_by)
                (field
                  name: (identifier))
                (field
                  name: (identifier)))
              (order_by
                (keyword_order)
                (keyword_by)
                (order_target
                  (field
                    name: (identifier))
                  (direction
                    (keyword_asc))
                  (keyword_nulls)
                  (keyword_first)))
              (window_frame
                (keyword_rows)
                (keyword_between)
                (frame_definition
                  start: (literal)
                  (keyword_preceding))
                (keyword_and)
                (frame_definition
                  end: (literal)
                  (keyword_following))
                (keyword_exclude)
                (keyword_current)
                (keyword_row)))))))
    (from
      (keyword_from)
      (relation
        (object_reference
          name: (identifier))))))

================================================================================
Window Functions complex example #2
================================================================================

SELECT
  a,
  c,
  MAX(c) OVER (
    PARTITION BY
      1,
      a,
      $1,
      CASE WHEN a > 100 THEN TRUE ELSE FALSE END,
      CAST(a AS DATE),
      a::DATE,
      (SELECT a FROM b),
      date_trunc(a),
      a * b
    ORDER BY
      1,
      a,
      $1,
      CASE WHEN a > $2 THEN TRUE ELSE FALSE END,
      CAST(a AS DATE),
      a::DATE,
      (SELECT a FROM b),
      date_trunc(a),
      a * b
  )
FROM
    tab;

--------------------------------------------------------------------------------

(program
  (statement
    (select
      (keyword_select)
      (select_expression
        (term
          value: (field
            name: (identifier)))
        (term
          value: (field
            name: (identifier)))
        (term
          value: (window_function
            (invocation
              (object_reference
                name: (identifier))
              parameter: (term
                value: (field
                  name: (identifier))))
            (keyword_over)
            (window_specification
              (partition_by
                (keyword_partition)
                (keyword_by)
                (literal)
                (field
                  name: (identifier))
                (parameter)
                (case
                  (keyword_case)
                  (keyword_when)
                  (binary_expression
                    left: (field
                      name: (identifier))
                    right: (literal))
                  (keyword_then)
                  (literal
                    (keyword_true))
                  (keyword_else)
                  (literal
                    (keyword_false))
                  (keyword_end))
                (cast
                  name: (keyword_cast)
                  parameter: (field
                    name: (identifier))
                  (keyword_as)
                  (keyword_date))
                (cast
                  (field
                    name: (identifier))
                  (keyword_date))
                (subquery
                  (select
                    (keyword_select)
                    (select_expression
                      (term
                        value: (field
                          name: (identifier)))))
                  (from
                    (keyword_from)
                    (relation
                      (object_reference
                        name: (identifier)))))
                (invocation
                  (object_reference
                    name: (identifier))
                  parameter: (term
                    value: (field
                      name: (identifier))))
                (binary_expression
                  left: (field
                    name: (identifier))
                  right: (field
                    name: (identifier))))
              (order_by
                (keyword_order)
                (keyword_by)
                (order_target
                  (literal))
                (order_target
                  (field
                    name: (identifier)))
                (order_target
                  (parameter))
                (order_target
                  (case
                    (keyword_case)
                    (keyword_when)
                    (binary_expression
                      left: (field
                        name: (identifier))
                      right: (parameter))
                    (keyword_then)
                    (literal
                      (keyword_true))
                    (keyword_else)
                    (literal
                      (keyword_false))
                    (keyword_end)))
                (order_target
                  (cast
                    name: (keyword_cast)
                    parameter: (field
                      name: (identifier))
                    (keyword_as)
                    (keyword_date)))
                (order_target
                  (cast
                    (field
                      name: (identifier))
                    (keyword_date)))
                (order_target
                  (subquery
                    (select
                      (keyword_select)
                      (select_expression
                        (term
                          value: (field
                            name: (identifier)))))
                    (from
                      (keyword_from)
                      (relation
                        (object_reference
                          name: (identifier))))))
                (order_target
                  (invocation
                    (object_reference
                      name: (identifier))
                    parameter: (term
                      value: (field
                        name: (identifier)))))
                (order_target
                  (binary_expression
                    left: (field
                      name: (identifier))
                    right: (field
                      name: (identifier))))))))))
    (from
      (keyword_from)
      (relation
        (object_reference
          name: (identifier))))))

================================================================================
Window function with empty count as aggregation
================================================================================

SELECT
  count(*) OVER (PARTITION BY c) AS w1
FROM tab1
;

--------------------------------------------------------------------------------

(program
  (statement
    (select
      (keyword_select)
      (select_expression
        (term
          value: (window_function
            (invocation
              (object_reference
                name: (identifier))
              parameter: (term
                value: (all_fields)))
            (keyword_over)
            (window_specification
              (partition_by
                (keyword_partition)
                (keyword_by)
                (field
                  name: (identifier)))))
          (keyword_as)
          alias: (identifier))))
    (from
      (keyword_from)
      (relation
        (object_reference
          name: (identifier))))))
