使用聚合函数时Postgresql列的最后一个值

时间:2018-04-01 22:07:35

标签: sql postgresql

我有以下工作查询:

select children.autor as child,  parents.autor as parent, count(*) from comments children
left join comments parents on (children.parentid = parents.commentid)
group by child, parent
order by count(*) desc
limit 4;

产生以下输出:

    child           |       parent        | count
peter               | max                 |   154
alex                | peter               |   122
peter               | kARL                |    82
stephen             | alex                |    50

现在,评论表还有一个“bodytext”列,它是实际的评论,我希望在每对子和父对的选择中包含最后一条评论。

所以在第一行我想要peter在回复max时写的最后一条评论。 到目前为止,我甚至不知道如何处理这个问题。一个子查询?某种窗口功能?

如果我使用(最大)bodytext,它几乎完全符合我的要求..只是我想要的最长的评论。

5 个答案:

答案 0 :(得分:2)

只将这一行添加到您的选择中:

(array_agg(children.bodytext ORDER BY children.commentid DESC))[1] AS last_comment

它将为每个组创建一个包含所有注释的数组,注释将按照指定的顺序排序(通过children.commentid DESC),然后你只需要数组的第一个元素=最后一个注释。

整个代码:

SELECT
  children.autor AS child,
  parents.autor AS parent,
  count(*),
  (array_agg(children.bodytext ORDER BY children.commentid DESC))[1] AS last_comment
FROM
  comments AS children
  LEFT JOIN comments AS parents
    ON (children.parentid = parents.commentid)
GROUP BY child, parent
ORDER BY count(*) DESC;

答案 1 :(得分:1)

这有两种方法。一个使用窗口/分析函数,尤其是first_value()。另一个使用数组。

第一种方法的一个例子:

select distinct c.autor as child,  cp.autor as parent,
       count(*) over (partition by c.autor, cp.autor) as cnt,
       first_value(c.bodytext) over (partition by c.autor, cp.auto order by ? desc)
from comments c left join
     comments cp
     on c.parentid = cp.commentid
order by cnt desc
limit 4;

?用于指定排序的列。

答案 2 :(得分:0)

如果commentid按时间顺序排列,则应该这样做。添加了max(c.commentid)的查询在此处称为query1,然后用于最后bodytext加入的外部查询:

with query1 as (
  select c.autor child, p.autor parent, count(*) cnt, max(c.commentid) id_last
  from       comments c
  left join  comments p on p.commentid=c.commentid
  group by c.autor, p.autor
)
select q.child, q.parent, q.cnt, t.bodytext comment_last
from      query1   q
left join comments t on t.commentid = q.id_last
order by t.cnt desc
limit 4;

不确定是否需要left。取决于您的数据和您想要的。 (顺便说一下,autor也许应该是作者)

答案 3 :(得分:0)

假设最新的bodytext具有最高commentid。使用窗口函数FIRST_VALUE获取最新的bodytextCOUNT以获取每组子/父组中的计数。使用DISTINCT消除重复项。

select distinct child, parent, 
first_value(bodytext) over (partition by child, parent order by commentid desc) bodytext,
count(*) over (partition by child, parent ) count
from
(select children.autor as child,  parents.autor as parent, children.bodytext, children.commentid 
from comments children
left join comments parents on (children.parentid = parents.commentid )) t
order by count desc
limit 4;

答案 4 :(得分:0)

由于您只检索4行,因此子查询在这里应该可以正常运行,因为它只应针对提取的行进行评估。

select children.autor as child,  parents.autor as parent, count(*),
  (select bodytext
   from comments
   where commentid = max(child.commentid)) as last_comment
from comments children
left join comments parents on (children.parentid = parents.commentid)
group by child, parent
order by count(*) desc
limit 4;