fixes #551 by supporting multiple window clauses
Signed-off-by: Sean Corfield <sean@corfield.org>
This commit is contained in:
parent
6fa606ffd5
commit
21ce3a2242
4 changed files with 64 additions and 2 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
* 2.6.next in progress
|
* 2.6.next in progress
|
||||||
|
* Fix [#551](https://github.com/seancorfield/honeysql/issues/551) by supporting multiple `WINDOW` clauses.
|
||||||
* Fix [#549](https://github.com/seancorfield/honeysql/issues/549) by using `:bb` conditionals to support Babashka (and still support Clojure 1.9.0), and add testing against Babashka so it is fully-supported as a target via PR [#550](https://github.com/seancorfield/honeysql/pull/550) [@borkdude](https://github.com/borkdude)
|
* Fix [#549](https://github.com/seancorfield/honeysql/issues/549) by using `:bb` conditionals to support Babashka (and still support Clojure 1.9.0), and add testing against Babashka so it is fully-supported as a target via PR [#550](https://github.com/seancorfield/honeysql/pull/550) [@borkdude](https://github.com/borkdude)
|
||||||
* Address [#532](https://github.com/seancorfield/honeysql/issues/532) by adding support for `EXCLUDE` and `RENAME` and starting to write tests for XTDB compatibility.
|
* Address [#532](https://github.com/seancorfield/honeysql/issues/532) by adding support for `EXCLUDE` and `RENAME` and starting to write tests for XTDB compatibility.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1090,7 +1090,7 @@ but is rendered into the SQL later in precedence order.
|
||||||
|
|
||||||
## window, partition-by (and over)
|
## window, partition-by (and over)
|
||||||
|
|
||||||
`:window` accepts a pair of SQL entity (the window name)
|
`:window` accept alternating pairs of SQL entity (the window name)
|
||||||
and the window "function" as a SQL clause (a hash map).
|
and the window "function" as a SQL clause (a hash map).
|
||||||
|
|
||||||
`:partition-by` accepts the same arguments as `:select` above
|
`:partition-by` accepts the same arguments as `:select` above
|
||||||
|
|
@ -1116,6 +1116,25 @@ SELECT id, AVG(salary) OVER (PARTITION BY department ORDER BY designation ASC) A
|
||||||
FROM employee
|
FROM employee
|
||||||
WINDOW w AS (PARTITION BY department)
|
WINDOW w AS (PARTITION BY department)
|
||||||
"]
|
"]
|
||||||
|
;; multiple windows:
|
||||||
|
user=> (sql/format {:select [:id
|
||||||
|
[[:over
|
||||||
|
[[:avg :salary]
|
||||||
|
{:partition-by [:department]
|
||||||
|
:order-by [:designation]}
|
||||||
|
:Average]
|
||||||
|
[[:max :salary]
|
||||||
|
:w
|
||||||
|
:MaxSalary]]]]
|
||||||
|
:from [:employee]
|
||||||
|
:window [:w {:partition-by [:department]}
|
||||||
|
:x {:partition-by [:salary]}]}
|
||||||
|
{:pretty true})
|
||||||
|
["
|
||||||
|
SELECT id, AVG(salary) OVER (PARTITION BY department ORDER BY designation ASC) AS Average, MAX(salary) OVER w AS MaxSalary
|
||||||
|
FROM employee
|
||||||
|
WINDOW w AS (PARTITION BY department), x AS (PARTITION BY salary)
|
||||||
|
"]
|
||||||
;; easier to write with helpers (and easier to read!):
|
;; easier to write with helpers (and easier to read!):
|
||||||
user=> (sql/format (-> (select :id
|
user=> (sql/format (-> (select :id
|
||||||
(over [[:avg :salary] (-> (partition-by :department) (order-by :designation)) :Average]
|
(over [[:avg :salary] (-> (partition-by :department) (order-by :designation)) :Average]
|
||||||
|
|
@ -1128,6 +1147,18 @@ SELECT id, AVG(salary) OVER (PARTITION BY department ORDER BY designation ASC) A
|
||||||
FROM employee
|
FROM employee
|
||||||
WINDOW w AS (PARTITION BY department)
|
WINDOW w AS (PARTITION BY department)
|
||||||
"]
|
"]
|
||||||
|
;; multiple window clauses:
|
||||||
|
user=> (sql/format (-> (select :id
|
||||||
|
(over [[:avg :salary] (-> (partition-by :department) (order-by :designation)) :Average]
|
||||||
|
[[:max :salary] :w :MaxSalary]))
|
||||||
|
(from :employee)
|
||||||
|
(window :w (partition-by :department))
|
||||||
|
(window :x (partition-by :salary))) {:pretty true})
|
||||||
|
["
|
||||||
|
SELECT id, AVG(salary) OVER (PARTITION BY department ORDER BY designation ASC) AS Average, MAX(salary) OVER w AS MaxSalary
|
||||||
|
FROM employee
|
||||||
|
WINDOW w AS (PARTITION BY department), x AS (PARTITION BY salary)
|
||||||
|
"]
|
||||||
```
|
```
|
||||||
|
|
||||||
The window function in the `:over` expression may be `{}` or `nil`:
|
The window function in the `:over` expression may be `{}` or `nil`:
|
||||||
|
|
|
||||||
|
|
@ -953,6 +953,9 @@
|
||||||
(defn- format-selector [k xs]
|
(defn- format-selector [k xs]
|
||||||
(format-selects k [xs]))
|
(format-selects k [xs]))
|
||||||
|
|
||||||
|
(defn- format-window [k xs]
|
||||||
|
(format-selects k (into [] (partition-all 2 xs))))
|
||||||
|
|
||||||
(declare columns-from-values)
|
(declare columns-from-values)
|
||||||
|
|
||||||
(defn- format-insert [k table]
|
(defn- format-insert [k table]
|
||||||
|
|
@ -1643,7 +1646,7 @@
|
||||||
:where #'format-on-expr
|
:where #'format-on-expr
|
||||||
:group-by #'format-group-by
|
:group-by #'format-group-by
|
||||||
:having #'format-on-expr
|
:having #'format-on-expr
|
||||||
:window #'format-selector
|
:window #'format-window
|
||||||
:partition-by #'format-selects
|
:partition-by #'format-selects
|
||||||
:order-by #'format-order-by
|
:order-by #'format-order-by
|
||||||
:limit #'format-on-expr
|
:limit #'format-on-expr
|
||||||
|
|
|
||||||
|
|
@ -533,6 +533,33 @@
|
||||||
" MAX(salary) OVER w AS MaxSalary"
|
" MAX(salary) OVER w AS MaxSalary"
|
||||||
" FROM employee"
|
" FROM employee"
|
||||||
" WINDOW w AS (PARTITION BY department)")]))
|
" WINDOW w AS (PARTITION BY department)")]))
|
||||||
|
;; multiple window tests
|
||||||
|
(is (= (-> (select :id
|
||||||
|
(over [[:avg :salary] (-> (partition-by :department) (order-by :designation)) :Average]
|
||||||
|
[[:max :salary] :w :MaxSalary]))
|
||||||
|
(from :employee)
|
||||||
|
(window :w (partition-by :department))
|
||||||
|
(window :x (partition-by :salary))
|
||||||
|
sql/format)
|
||||||
|
[(str "SELECT id,"
|
||||||
|
" AVG(salary) OVER (PARTITION BY department ORDER BY designation ASC) AS Average,"
|
||||||
|
" MAX(salary) OVER w AS MaxSalary"
|
||||||
|
" FROM employee"
|
||||||
|
" WINDOW w AS (PARTITION BY department)"
|
||||||
|
", x AS (PARTITION BY salary)")]))
|
||||||
|
(is (= (-> (select :id
|
||||||
|
(over [[:avg :salary] (-> (partition-by :department) (order-by :designation)) :Average]
|
||||||
|
[[:max :salary] :w :MaxSalary]))
|
||||||
|
(from :employee)
|
||||||
|
(window :w (partition-by :department)
|
||||||
|
:x (partition-by :salary))
|
||||||
|
sql/format)
|
||||||
|
[(str "SELECT id,"
|
||||||
|
" AVG(salary) OVER (PARTITION BY department ORDER BY designation ASC) AS Average,"
|
||||||
|
" MAX(salary) OVER w AS MaxSalary"
|
||||||
|
" FROM employee"
|
||||||
|
" WINDOW w AS (PARTITION BY department)"
|
||||||
|
", x AS (PARTITION BY salary)")]))
|
||||||
;; test nil / empty window function clause:
|
;; test nil / empty window function clause:
|
||||||
(is (= (-> (select :id
|
(is (= (-> (select :id
|
||||||
(over [[:avg :salary] {} :Average]
|
(over [[:avg :salary] {} :Average]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue