我们目前正在将我们的数据库后端从Firebird迁移到PostgreSQL。我们将NHibernate用作ORM,尽管SQL中存在一些差异,但转换仍然非常简单。
我们有一个查询,我们使用NHibernate.CreateSQLQuery执行,因为我们自己构建SQL。该查询返回传入的UserID中最近访问最多5个Ninja名称的字符串List。
使用以下SQL在Firebird中没问题;
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
返回有序(按访问日期降序排列)字符串列表。
现在在PostgreSQL中,我们遇到了这个简单查询的问题;
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
似乎我们无法返回单个“不同”数据列,并且在未包含在select中的单独列上执行排序。除非我们在select中包含Access_Date列,否则上述SQL中的任何变体都不起作用。
我们如何在PostgreSQL中解决这个简单的查询?
旁注:这是我们的忍者管理系统的一个重要问题,忍者坚持认为它有效!!!
答案 0 :(得分:2)
此查询应该是等效的:
SELECT n.ninja_name
,max(n.ninja_access_date) AS max_access_date
FROM ninja_access na
JOIN ninjas n USING (ninja_id)
WHERE na.user_id = 1
GROUP BY n.ninja_name
ORDER BY 2 DESC
LIMIT 5;
ORDER BY 2
只是ORDER BY max(n.ninja_access_date)
。max(n.ninja_access_date)
按ninja_name
获取最多最近条目。JOIN ninjas n USING (ninja_id)
是JOIN ninjas n ON n.ninja_id = na.ninja_id
您不必在SELECT列表中包含访问日期。仅获取名称:
SELECT n.ninja_name
FROM ninja_access na
JOIN ninjas ni USING (ninja_id)
WHERE na.user_id = 1
GROUP BY n.ninja_name
ORDER BY max(n.ninja_access_date) DESC
LIMIT 5;