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
|
||||
|
||||
* 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)
|
||||
* 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` 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).
|
||||
|
||||
`: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
|
||||
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!):
|
||||
user=> (sql/format (-> (select :id
|
||||
(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
|
||||
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`:
|
||||
|
|
|
|||
|
|
@ -953,6 +953,9 @@
|
|||
(defn- format-selector [k xs]
|
||||
(format-selects k [xs]))
|
||||
|
||||
(defn- format-window [k xs]
|
||||
(format-selects k (into [] (partition-all 2 xs))))
|
||||
|
||||
(declare columns-from-values)
|
||||
|
||||
(defn- format-insert [k table]
|
||||
|
|
@ -1643,7 +1646,7 @@
|
|||
:where #'format-on-expr
|
||||
:group-by #'format-group-by
|
||||
:having #'format-on-expr
|
||||
:window #'format-selector
|
||||
:window #'format-window
|
||||
:partition-by #'format-selects
|
||||
:order-by #'format-order-by
|
||||
:limit #'format-on-expr
|
||||
|
|
|
|||
|
|
@ -533,6 +533,33 @@
|
|||
" MAX(salary) OVER w AS MaxSalary"
|
||||
" FROM employee"
|
||||
" 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:
|
||||
(is (= (-> (select :id
|
||||
(over [[:avg :salary] {} :Average]
|
||||
|
|
|
|||
Loading…
Reference in a new issue