【问题标题】:How to select the latest record of each month?如何选择每个月的最新记录?
【发布时间】:2021-11-01 13:06:03
【问题描述】:

我想和sql做朋友真的很难。请帮忙!
我有包含 3 年客户主记录的历史记录表。 表格如下所示:

表 A:

| ID  | Name | Number|Date(in Timestamp)|
|:--- |:----:|:-----:|-----------------:|
|123  | John | 101   |20210101 01:11:15 |
|123  | John | 102   |20210103 01:11:15 |
|123  | John | 103   |20210301 01:11:15 |
|123  | John | 104   |20210325 01:11:15 |
|123  | John | 105   |20210415 01:11:15 |
|123  | John | 106   |20210416 01:11:15 |
|124  | Mary | 201   |20210101 01:11:15 |
|124  | Mary | 202   |20210103 01:11:15 |
|124  | Mary | 203   |20210201 01:11:15 |
|124  | Mary | 204   |20210225 01:11:15 |
|124  | Mary | 204   |20210315 01:11:15 |
|124  | Mary | 205   |20210416 01:11:15 |

我需要知道每个客户在每个月底的记录是什么。

预期结果是:

| ID  | Name | Number|Date    |
|123  | John | 102   |20210131|
|123  | John | 104   |20210331|
|123  | John | 106   |20210430|
|124  | Mary | 202   |20210131|
|124  | Mary | 204   |20210228|
|124  | Mary | 204   |20210331|
|124  | Mary | 205   |20210430|

我在 sql 下创建,但看起来我不能使用 substr 作为时间戳。 有没有其他方法可以做到这一点?非常感谢任何帮助!

select * from (select t1.id, t1.name, t1.number, t1.date,
ROW_NUMBER() over (partition by substr(date,1,6) order by date desc) as Rowrank
from tableA t1)sub where Rowrank = 1

【问题讨论】:

  • 样本数据很好,但您也应该指定预期的结果。
  • 感谢您的评论!我编辑了它。
  • @Jojo10478,请查看我的回答。

标签: sql database teradata teradatasql rdbms


【解决方案1】:

在 Teradata 中,您可能会发现 trunc() 是一个简单的方法:

select a.id, a.name, a.number, a.date
from (select a.*,
             row_number() over (partition by trunc(date, 'MON') order by date desc) as seqnum
      from tableA a
     ) a
where seqnum = 1;

Teradata 还支持限定:

select a.id, a.name, a.number, a.date
from tableA a
qualify row_number() over (partition by trunc(date, 'MON') order by date desc) = 1

【讨论】:

  • 您还可以使用QUALIFY 子句select * from tableA QUALIFY row_number() over (partition by trunc(date, 'MON') order by "date" desc) = 1; 摆脱Teradata 中的子查询
  • 天哪,这就是我要找的!我只需要在分区中添加“a.id”和 trunc(date, 'YEAR'),瞧!现在我可以睡个好觉了。非常感谢!
  • 嗨@JNevill,我尝试使用 QUALIFY,它给了我相同的结果!我想我会使用它而不是子查询。谢谢!
  • @Jojo10478:不需要添加trunc(date, 'YEAR'),MON 会截断到月初。顺便说一句,last_day(date) 也可以使用。
  • @dnoeth,你是对的!没有trunc(date, 'YEAR'),查询给了我相同的输出。关于last_day(date),是的,我刚刚发现我可以用它来输出月末的日期。感谢您的评论!
【解决方案2】:

试试这个答案:

根据Id, year and Month从时间戳值和分区中获取YearMonth值。

select * 
from (
    select t1.id, t1.name, t1.number, t1.date,
    ROW_NUMBER() over (partition by t1.id,YEAR(date_format(str_to_date(t1.date, '%Y%m%d'),'%Y-%m-%d')),MONTH(date_format(str_to_date(t1.date, '%Y%m%d'),'%Y-%m-%d')) order by date desc) as Rowrank
    from tableA t1
     )sub where Rowrank = 1

【讨论】:

  • 我在“,”和“YEAR”之间有语法错误。对于“ROW_NUMBER() over (partition by t1.id,YEAR”这一行。恐怕这种语法或格式不适用于 Teradata 数据库。
  • 以前的标签是mysql,现在你把它改成了teradata。请尝试在 teradata 中执行相同的模式,例如将时间戳值转换为日期并获取 monthyear,然后使用列进行分区
  • 是的,很抱歉那是我的错。老实说,我刚刚意识到mysql是另一个系统。我将尝试在 teradata 中寻找相同的模式。非常感谢!
  • 这种模式在 teradata 中给了我预期的结果。再次感谢您的想法!
猜你喜欢
  • 2014-11-19
  • 2021-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-13
  • 1970-01-01
  • 2020-06-21
  • 1970-01-01
相关资源
最近更新 更多