PostgreSQL - select distinct -按字段顺序不返回

本文关键字:顺序 返回 字段 select distinct PostgreSQL | 更新日期: 2023-09-27 18:15:56

我们目前正在将数据库后端从Firebird迁移到PostgreSQL。我们使用NHibernate作为一个ORM,虽然在SQL上有一些不同,但这种转换相当轻松。

我们有一个使用NHibernate执行的查询。CreateSQLQuery,因为我们自己构建SQL。查询返回UserID中最近访问最多的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中的单独列上执行的。除非我们在select中包含Access_Date列,否则上述SQL中的任何变化都无法工作。

在PostgreSQL中如何解决这个简单的查询?

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

PostgreSQL - select distinct -按字段顺序不返回

这个查询应该是等价的:

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 2ORDER 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;