我使用这种方式(仅限postgresql):https://wiki.postgresql.org/wiki/First/last_%28aggregate%29
-- Create a function that always returns the first non-NULL item
CREATE OR REPLACE FUNCTION public.first_agg ( anyelement, anyelement )
RETURNS anyelement LANGUAGE sql IMMUTABLE STRICT AS $$
SELECT $1;
$$;
-- And then wrap an aggregate around it
CREATE AGGREGATE public.first (
sfunc = public.first_agg,
basetype = anyelement,
stype = anyelement
);
-- Create a function that always returns the last non-NULL item
CREATE OR REPLACE FUNCTION public.last_agg ( anyelement, anyelement )
RETURNS anyelement LANGUAGE sql IMMUTABLE STRICT AS $$
SELECT $2;
$$;
-- And then wrap an aggregate around it
CREATE AGGREGATE public.last (
sfunc = public.last_agg,
basetype = anyelement,
stype = anyelement
);
那么,您的示例应该大致如下:
SELECT FIRST(id), customer, FIRST(total)
FROM purchases
GROUP BY customer
ORDER BY FIRST(total) DESC;
CAVEAT:它忽略NULL行
编辑1-改用postgres扩展名
现在我用这种方式:http://pgxn.org/dist/first_last_agg/
要在ubuntu 14.04上安装:
apt-get install postgresql-server-dev-9.3 git build-essential -y
git clone git://github.com/wulczer/first_last_agg.git
cd first_last_app
make && sudo make install
psql -c 'create extension first_last_agg'
它是一个postgres扩展,为您提供第一个和最后一个函数;显然比上述方式更快。
编辑2-排序和筛选
如果使用聚合函数(如以下函数),则可以对结果进行排序,而无需对数据进行排序:
http://www.postgresql.org/docs/current/static/sql-expressions.html#SYNTAX-AGGREGATES
因此,具有排序的等效示例如下:
SELECT first(id order by id), customer, first(total order by id)
FROM purchases
GROUP BY customer
ORDER BY first(total);
当然,您可以根据您认为合适的情况在聚合中进行排序和过滤;这是非常强大的语法。