New versions: Dev (3.14) | Latest (3.13) | 3.12 | 3.11 | 3.10 | 3.9 | 3.8 | Old versions: 3.7 | 3.6 | 3.5 | 3.3

Filtering

Applies to ✅ Open Source Edition   ✅ Express Edition   ✅ Professional Edition   ✅ Enterprise Edition

The SQL standard specifies an optional FILTER clause, that can be appended to all aggregate functions including aggregated window functions. This is very useful, for example, to implement "pivot" tables, such as the following:

SELECT
  count(*),
  count(*) FILTER (WHERE TITLE LIKE 'A%'),
  count(*) FILTER (WHERE TITLE LIKE '%A%')
FROM BOOK
create.select(
         count(),
         count().filterWhere(BOOK.TITLE.like("A%")),
         count().filterWhere(BOOK.TITLE.like("%A%")))
      .from(BOOK)

Producing:

+-------+-------+-------+
| count | count | count |
+-------+-------+-------+
|     4 |     1 |     2 |
+-------+-------+-------+

Or, with GROUP BY:

SELECT
  AUTHOR_ID,
  count(*),
  count(*) FILTER (WHERE TITLE LIKE 'A%'),
  count(*) FILTER (WHERE TITLE LIKE '%A%')
FROM BOOK
GROUP BY AUTHOR_ID
create.select(
         BOOK.AUTHOR_ID,
         count(),
         count().filterWhere(BOOK.TITLE.like("A%")),
         count().filterWhere(BOOK.TITLE.like("%A%")))
      .from(BOOK)
      .groupBy(BOOK.AUTHOR_ID)

Producing:

+-----------+-------+-------+-------+
| AUTHOR_ID | count | count | count |
+-----------+-------+-------+-------+
|         1 |     2 |     1 |     1 |
|         2 |     2 |     0 |     1 |
+-----------+-------+-------+-------+

It is usually a good idea to calculate multiple aggregate functions in a single query, if this is possible, and FILTER helps here.

Only a few dialects implement native support for the FILTER clause. In all other databases, jOOQ emulates the clause using a CASE expression. Aggregate functions exclude NULL values from aggregation.

Dialect support

This example using jOOQ:

count().filterWhere(BOOK.TITLE.like("A%"))

Translates to the following dialect specific expressions:

-- ACCESS
count(SWITCH(BOOK.TITLE LIKE 'A%', 1))

-- ASE, AURORA_MYSQL, CUBRID, DB2, DERBY, FIREBIRD, HANA, INFORMIX, INGRES, MARIADB, MEMSQL, MYSQL, ORACLE, REDSHIFT, 
-- SQLDATAWAREHOUSE, SQLSERVER, SYBASE, TERADATA, VERTICA
count(CASE WHEN BOOK.TITLE LIKE 'A%' THEN 1 END)

-- AURORA_POSTGRES, COCKROACHDB, H2, HSQLDB, POSTGRES, SQLITE
count(*) FILTER (WHERE BOOK.TITLE LIKE 'A%')

(These are currently generated with jOOQ 3.14, see #10141)

The jOOQ Logo