First y Last postgresql aggregates y como usarlos en django.
Muchas veces nos encontramos en la situacion, cuando necesitamos sacar una lista ordenada de ultimos elementos (heterogeneos) agrupado por una "foreign key", y no sere de menos. Investigando y probando sobre el ORM de Django, a ver si se podria hacer algo, y ya perdidas todas la esperanzas me he topado con este articulo.
Como dice, MS access tiene un particular conjunto de Aggregates, llamadas First y Last, que nos permiten secar primero o el último elemento de una consulta. Como sabemos que Access no es perfecto, veremos de crear nuestro mundo perfecto en PostgreSQL (traducción literal).
Definicion de funciones y aggregates:
CREATE OR REPLACE FUNCTION first_element_state(anyarray, anyelement)
RETURNS anyarray AS
$$
SELECT CASE WHEN array_upper($1,1) IS NULL THEN array_append($1,$2) ELSE $1 END;
$$
LANGUAGE 'sql' IMMUTABLE;
CREATE OR REPLACE FUNCTION first_element(anyarray)
RETURNS anyelement AS
$$
SELECT ($1)[1] ;
$$
LANGUAGE 'sql' IMMUTABLE;
CREATE OR REPLACE FUNCTION last_element(anyelement, anyelement)
RETURNS anyelement AS
$$
SELECT $2;
$$
LANGUAGE 'sql' IMMUTABLE;
CREATE AGGREGATE first(anyelement) (
SFUNC=first_element_state,
STYPE=anyarray,
FINALFUNC=first_element
);
CREATE AGGREGATE last(anyelement) (
SFUNC=last_element,
STYPE=anyelement
);
Aplicando a la practica:
Ahora suponemos que tenemos Item's u que cada uno pertenece a un Design, ahora queremos sacar el último item insertado por cada Design.
Este seria un ejemplo de sql:
SELECT first(id) as id FROM (SELECT * FROM items WHERE code LIKE 'XXX%' ORDER BY created_date DESC)
as foo GROUP BY design_id;
Y usarlo en django es tan simple como:
Item.object.raw("SELECT first(id) as id FROM (SELECT * FROM items "
"ORDER BY created_date DESC) as foo GROUP BY design_id")