We’re currently migrating our database back-end from Firebird to PostgreSQL. We use NHibernate as an ORM and the transition has been quite painless albeit a few differences in SQL.
We have one query which we execute using NHibernate.CreateSQLQuery as we build the SQL ourselves. The query returns a string List of the most 5 most recently accessed Ninja names for the passed in UserID.
This was no problem in Firebird using the following SQL;
SELECT FIRST 5 DISTINCT NI.NINJA_NAME
FROM NINJA_ACCESS NA
INNER JOIN NINJAS NI ON NA.NINJA_ID = NI.NINJA_ID
WHERE NA.USER_ID = 1
ORDER BY NI.NINJA_ACCESS_DATE DESC
Returning an ordered (by access date descending) list of strings.
Now in PostgreSQL we are encountering problems with this simple query;
SELECT DISTINCT ON (NI.NINJA_NAME) NI.NINJA_NAME
FROM NINJA_ACCESS NA
INNER JOIN NINJAS NI ON NA.NINJA_ID = NI.NINJA_ID
WHERE NA.USER_ID = 1
ORDER BY NI.NINJA_ACCESS_DATE DESC
LIMIT 5
It appears that we cannot return a single “distinct” column of data with ordering being performed on a separate column that isn’t included in the select. Any variation in the above SQL doesn’t work unless we include the Access_Date column in the select.
Any ideas how we can resolve this simple query in PostgreSQL?
Side-note: This is an important query for our Ninja Management System, the Ninja’s insist that it work!!!
This query should be the equivalent:
ORDER BY 2is just shorthand forORDER BY max(n.ninja_access_date).max(n.ninja_access_date)to get the most recent entry perninja_name.And sort descending to get the most recent names.
JOIN ninjas n USING (ninja_id)is shorthand forJOIN ninjas n ON n.ninja_id = na.ninja_idYou don’t have to include the access date in the SELECT list. To only get the names: