在pg中支持nulls first/last的写法,并且因为pg的索引中可以存储null值,所以这种写法还支持索引。
而在Greenplum之前的版本中是不支持这种写法的:
select * from tbl order by id nulls first;
select id, last_value(key) over (partition by gid order by crt_time nulls first) from tbl ;
但是在新版本的Greenplum中可以使用了,并且也支持索引扫描,但是如果不支持这种写法我们该怎么改写呢?
其实要实现nulls first/last这种语法我们只要在排序时调整字段nulls排在前面还是后面即可。所以我们可以改写成:
select * from tbl order by (id is not null), id;
相当于
select * from tbl order by id nulls first;
select * from tbl order by (id is null), id;
相当于
select * from tbl order by id nulls last;
例如:
postgres=# select * from t4 order by (id is not null),id;
id | info
----+----------------------------------
| e8a03a9114ad7e2a20a089bc8e976ced
| eda4245be143d05d873bd7a96543e741
| 7ec3032fd84ae3377173aff3e0affff2
| 6fb3808909322badc94e542dbc011d0f
1 | acb6661d320f25133476670879b154ab
2 | acb6661d320f25133476670879b154ab
3 | acb6661d320f25133476670879b154ab
4 | acb6661d320f25133476670879b154ab
5 | acb6661d320f25133476670879b154ab
(9 rows)
postgres=# select * from t4 order by (id is null),id;
id | info
----+----------------------------------
1 | acb6661d320f25133476670879b154ab
2 | acb6661d320f25133476670879b154ab
3 | acb6661d320f25133476670879b154ab
4 | acb6661d320f25133476670879b154ab
5 | acb6661d320f25133476670879b154ab
| e8a03a9114ad7e2a20a089bc8e976ced
| eda4245be143d05d873bd7a96543e741
| 7ec3032fd84ae3377173aff3e0affff2
| 6fb3808909322badc94e542dbc011d0f
(9 rows)
同样在窗口函数中我们也可以这样实现,不过两者还是有一些区别,我们这种写法是不能使用索引的。
postgres=# EXPLAIN select * from t4 order by (id is null),id;
QUERY PLAN
----------------------------------------------------------------------------------------
Gather Motion 2:1 (slice1; segments: 2) (cost=9513.72..9763.75 rows=100009 width=37)
Merge Key: (id IS NULL), id
-> Sort (cost=9513.72..9763.75 rows=50005 width=37)
Sort Key: (id IS NULL), id
-> Seq Scan on t4 (cost=0.00..1208.09 rows=50005 width=37)
Settings: enable_seqscan=on
Optimizer status: legacy query optimizer
(7 rows)
而普通的nulls first/last语法则可以使用索引。
postgres=# EXPLAIN select * from t4 order by id nulls last;
QUERY PLAN
-------------------------------------------------------------------------------------
Gather Motion 2:1 (slice1; segments: 2) (cost=0.00..9415.27 rows=100009 width=37)
Merge Key: id
-> Index Scan using idx_t4 on t4 (cost=0.00..9415.27 rows=50005 width=37)
Settings: enable_seqscan=on
Optimizer status: legacy query optimizer
(5 rows)