2011-11-29 119 views
2

我们目前正在将我们的数据库后端从Firebird迁移到PostgreSQL。我们使用NHibernate作为ORM,尽管SQL有一些差异,但转换已经非常轻松。PostgreSQL - select distinct - 按字段顺序不返回select

我们有一个查询,我们使用NHibernate.CreateSQLQuery执行,因为我们自己构建SQL。该查询返回一个字符串列表,其中包含最近访问过的用户ID中最多5个忍者名称。

这在Firebird中没有问题,使用以下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 

返回字符串命令(通过访问日期倒序排列)名单。

现在在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中包含Access_Date列,否则上述SQL中的任何变体都不起作用。

任何想法如何解决这个简单的查询在PostgreSQL?

旁注:这是忍者管理系统的一个重要查询,忍者坚持它的工作!

+0

也许会重写为GROUP BY? – Kenaniah

+0

对于忍者查询 – MurifoX

回答

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; 
+0

感谢Erwin,一个明确的答案,我很欣赏SQL语法和替代“单列选择”方法的解释。 – paligap