如何用SQL中前几天的最新值替换丢失的行?

时间:2019-09-16 13:00:30

标签: sql amazon-athena

这是我对所有雅典娜SQL专家的第一个问题

我有一个雅典娜数据库,其中的表包含过去两年的用户数据。 该表以实木复合地板格式存储在S3中,并按日期(称为dt的列)进行分区。

表的每一行都包含用户ID,时间戳,一些属性(prop1,prop2,prop3)和分区键dt。

每天(dt)每个用户我有零个,一个或多个条目。 我需要编写一个Athena SQL查询,该查询输出最近两年的所有数据,每天(dt)包含最新的用户信息。 这意味着,如果某个特定dt中不存在最新的用户信息,则我需要跨时间传播这些信息。

示例输入表:

|    dt    |UserId|     timestamp          |p1 |p2 |p3 |
|----------|------|------------------------|---|---|---|
|01/09/2019|    A |2019-09-01T09:50:04.082Z|x  |y  |z  |
|01/09/2019|    A |2019-09-01T10:52:04.082Z|r  |t  |g  |
|01/09/2019|    B |2019-09-01T11:02:04.082Z|a  |s  |d  |
|01/09/2019|    C |2019-09-01T10:10:04.082Z|z  |x  |c  |
|----------|------|------------------------|---|---|---|
|02/09/2019|    B |2019-09-02T11:02:04.082Z|a  |s  |d  |
|----------|------|------------------------|---|---|---|
|03/09/2019|    A |2019-09-03T12:50:04.082Z|fd |swq|qw |
|03/09/2019|    B |2019-09-03T11:02:04.082Z|wre|ewr|we |
|----------|------|------------------------|---|---|---|
|04/09/2019|    J |2019-09-04T11:02:04.082Z|dc |qw |w3 |
|----------|------|------------------------|---|---|---|
|05/09/2019|    A |2019-09-05T11:02:04.082Z|qdw|qw |rg |
|05/09/2019|    B |2019-09-05T11:02:04.082Z|g  |de |ew |
|05/09/2019|    J |2019-09-05T11:02:04.082Z|egr|gre|rg |

示例输出表:

|   dt     |UserId|     timestamp          |p1 |p2 |p3 |
|----------|------|------------------------|---|---|---|
|01/09/2019|   A  |2019-09-01T10:52:04.082Z|r  | t | g |
|01/09/2019|   B  |2019-09-01T11:02:04.082Z|a  | s | d |
|01/09/2019|   C  |2019-09-01T10:10:04.082Z|z  | x | c |
|----------|------|------------------------|---|---|---|
|02/09/2019|   B  |2019-09-02T11:02:04.082Z|a  | s | d |
|02/09/2019|   A  |2019-09-01T10:52:04.082Z|r  | t | g |
|02/09/2019|   C  |2019-09-01T10:10:04.082Z|z  | x | c |
|----------|------|------------------------|---|---|---|
|03/09/2019|   A  |2019-09-03T12:50:04.082Z|fd |swq|qw |
|03/09/2019|   B  |2019-09-03T11:02:04.082Z|wre|ewr|we |
|03/09/2019|   C  |2019-09-01T10:10:04.082Z|z  | x |c  |
|----------|------|------------------------|---|---|---|
|04/09/2019|   J  |2019-09-04T11:02:04.082Z|dc |qw |w3 |
|04/09/2019|   A  |2019-09-03T12:50:04.082Z|fd |swq|qw |
|04/09/2019|   B  |2019-09-03T11:02:04.082Z|wre|ewr|we |
|04/09/2019|   C  |2019-09-01T10:10:04.082Z|z  |x  |c  |
|----------|------|------------------------|---|---|---|
|05/09/2019|   A  |2019-09-05T11:02:04.082Z|qdw|qw |rg |
|05/09/2019|   B  |2019-09-05T11:02:04.082Z|g  |de |ew |
|05/09/2019|   J  |2019-09-05T11:02:04.082Z|egr|gre|rg |
|05/09/2019|   C  |2019-09-01T10:10:04.082Z|z  |x  |c  |
|----------|------|------------------------|---|---|---|

编辑:

为了使尝试方法更容易,这里是一个查询,用于创建上表并从中选择所有项:

WITH the_table AS (
  SELECT '01/09/2019' AS dt, 'A' AS user_id, '2019-09-01T09:50:04.082Z' AS timestamp, 'x' as p1, 'y' as p2, 'z' as p3
  UNION ALL SELECT '01/09/2019', 'A', '2019-09-01T10:52:04.082Z', 'r', 't', 'g'
  UNION ALL SELECT '01/09/2019', 'B', '2019-09-01T11:02:04.082Z', 'a', 's', 'd'
  UNION ALL SELECT '01/09/2019', 'C', '2019-09-01T10:10:04.082Z', 'z', 'x', 'c'
  UNION ALL SELECT '02/09/2019', 'B', '2019-09-02T11:02:04.082Z', 'a', 's', 'd'
  UNION ALL SELECT '03/09/2019', 'A', '2019-09-03T12:50:04.082Z', 'fd', 'swq', 'qw'
  UNION ALL SELECT '03/09/2019', 'B', '2019-09-03T11:02:04.082Z', 'wre', 'ewr', 'we'
  UNION ALL SELECT '04/09/2019', 'J', '2019-09-04T11:02:04.082Z', 'dc', 'qw', 'w3'
  UNION ALL SELECT '05/09/2019', 'A', '2019-09-05T11:02:04.082Z', 'qdw', 'qw', 'rg'
  UNION ALL SELECT '05/09/2019', 'B', '2019-09-05T11:02:04.082Z', 'g', 'de', 'ew'
  UNION ALL SELECT '05/09/2019', 'J', '2019-09-05T11:02:04.082Z', 'egr', 'gre', 'rg'
  ORDER BY dt ASC
)

SELECT * from the_table

1 个答案:

答案 0 :(得分:0)

我认为关键是MAX_BY聚合函数。您要做的是按日期和用户ID分组,并在所有其他列上使用MAX_BY,如下所示:

SELECT
  dt,
  user_id,
  MAX_BY(p1, timestamp) AS p1,
  MAX_BY(p2, timestamp) AS p2,
  -- etc.
FROM the_table
GROUP BY dt, user_id

MAX_BY返回第二列具有最高值的组中第一列的值,即在第一种情况下最高p1值的timestamp值。 / p>