Иногда при объединении данных с SQL мы хотели бы добавить несколько дополнительных фильтров. Например, рассмотрим следующие данные мирового банка:
ВВП на душу населения (в текущих ценах)
1
2
3
4
5
6
7
8
9
|
2009 2010 2011 2012 CA 40 , 764 47 , 465 51 , 791 52 , 409 DE 40 , 270 40 , 408 44 , 355 42 , 598 FR 40 , 488 39 , 448 42 , 578 39 , 759 GB 35 , 455 36 , 573 38 , 927 38 , 649 IT 35 , 724 34 , 673 36 , 988 33 , 814 JP 39 , 473 43 , 118 46 , 204 46 , 548 RU 8 , 616 10 , 710 13 , 324 14 , 091 US 46 , 999 48 , 358 49 , 855 51 , 755 |
И структура таблицы:
1
2
3
4
5
|
CREATE TABLE countries ( code CHAR (2) NOT NULL , year INT NOT NULL , gdp_per_capita DECIMAL (10, 2) NOT NULL ); |
Теперь предположим, что мы хотели бы найти число стран с ВВП выше 40 000 за каждый год.
Со стандартным SQL: 2003, а теперь и с недавно выпущенным PostgreSQL 9.4 мы можем теперь воспользоваться новым предложением FILTER
, которое позволяет нам написать следующий запрос:
1
2
3
4
5
6
7
|
SELECT year , count (*) FILTER ( WHERE gdp_per_capita >= 40000) FROM countries GROUP BY year |
Приведенный выше запрос теперь даст:
1
2
3
4
5
6
|
year count ------------ 2012 4 2011 5 2010 4 2009 4 |
И это еще не все! Как всегда, вы можете использовать любую агрегатную функцию также как оконную функцию, просто добавив в конец предложение OVER()
:
1
2
3
4
5
6
7
8
9
|
SELECT year , code, gdp_per_capita, count (*) FILTER ( WHERE gdp_per_capita >= 40000) OVER (PARTITION BY year ) FROM countries |
Результат будет выглядеть примерно так:
1
2
3
4
5
6
|
year code gdp_per_capita count ------------------------------------ 2009 CA 40764.00 4 2009 DE 40270.00 4 2009 FR 40488.00 4 2009 GB 35455.00 4 |
jOOQ 3.6 также будет поддерживать новое предложение FILTER для агрегатных функций
Хорошие новости для пользователей jOOQ. Вы можете написать тот же запрос с jOOQ интуитивно как таковой:
1
2
3
4
5
6
7
8
9
|
DSL.using(configuration) .select( COUNTRIES.YEAR, count().filterWhere( COUNTRIES.GDP_PER_CAPITA.ge( 40000 ) )) .from(COUNTRIES) .groupBy(COUNTRIES.YEAR) .fetch(); |
… и
01
02
03
04
05
06
07
08
09
10
|
DSL.using(configuration) .select( COUNTRIES.YEAR, COUNTRIES.CODE, COUNTRIES.GDP_PER_CAPITA count().filterWhere( COUNTRIES.GDP_PER_CAPITA.ge( 40000 )) .over(partitionBy(COUNTRIES.YEAR))) .from(COUNTRIES) .fetch(); |
И лучше всего то, что jOOQ (как обычно) эмулирует вышеприведенное предложение для вас, если вы не используете PostgreSQL. Эквивалентный запрос будет:
1
2
3
4
5
6
7
|
SELECT year , count ( CASE WHEN gdp_per_capita >= 40000 THEN 1 END ) FROM countries GROUP BY year |
Подробнее о том, что нового в PostgreSQL 9.4, читайте здесь
Ссылка: | Замечательное предложение FILTER PostgreSQL 9.4 / SQL: 2003 для агрегатных функций от нашего партнера по JCG Лукаса Эдера из блога JAVA, SQL и AND JOOQ . |