生成第一篇文章和最后一篇文章之间的天数差异

问题描述 投票:0回答:1

我正在从一个网站学习 SQL,他们有 这个问题,我下面的尝试还不够,需要输入。

问题总结:
“找出 2021 年最后一篇帖子和第一篇帖子之间的天数差异。”

数据:

posts

Column Name   Type
user_id       integer
post_id       integer
post_date     timestamp
post_content  text

样本数据:

user_id post_id post_date           post_content
151652  599415  07/10/2021 12:00:00 Need a hug
661093  624356  07/29/2021 13:00:00 Bed. Class 8-12.
004239  784254  07/04/2021 11:00:00 Happy 4th of July!
661093  442560  07/08/2021 14:00:00 Just going to cry myself to sleep 
151652  111766  07/12/2021 19:00:00 I'm so done with covid - need travelling ASAP!

输出示例:

user_id days_between
151652  2
661093  21

我的回答尝试需要大量阅读,而我想出的最好的答案是 PostgreSQL:

WITH
target_year AS
(
  SELECT *
  FROM
  (
    SELECT 
      user_id,
      post_date, 
      dense_rank() over(PARTITION BY user_id order by user_id desc) as n
    FROM posts
    where EXTRACT('year' from post_date)=2021
    order by user_id DESC
  ) as x
  where n <=2
),

target_user AS
(
SELECT  user_id,
  post_date::date - lag(post_date::date) over (order by user_id) from target_year
)

select * from target_user
order by user_id

我得到的结果是:

user_id column
151325  NULL
151652  -207
151652  244
151652  -307
178425  55
423967  42
661093  105
661093  21
661093  -206

我对以上内容感到困惑

  1. 我在

    where n <=2
    子句
    with
    中选择了
    target_year
    。我预计每组最多只有两个结果,但上面显示至少有三个结果。我的逻辑怎么被打破了?

  2. 我的理解是,通过使用类型

    ::date
    ,它会将日期强制转换为天。如何使日期成为绝对日期,以及为什么它们是负数?我对逻辑的理解是,因为我按日期降序排列,前两个结果应该只从较小的数字 (lag(post_date::date)) 中减去较大的数字 (
    post_date::date
    ),因此负数的存在应该不可能,我的逻辑怎么错了?

  3. 此外,当我将

    where n <=2
    子句
    where n >=2
    中的逻辑从
    with
    更改为
    target_year
    时。我没有得到任何结果。我预计至少有两到三个条目的人会在那里。为什么这个逻辑不起作用?

sql postgresql aggregate-functions greatest-n-per-group
1个回答
0
投票

可以在单个查询级别中使用普通聚合来完成:

SELECT user_id
     , max(post_date)::date - min(post_date)::date AS days_between
FROM   posts
WHERE  post_date >= '2021-01-01'
AND    post_date <  '2022-01-01'
GROUP  BY user_id
HAVING count(*) > 1
ORDER  BY user_id;
© www.soinside.com 2019 - 2024. All rights reserved.