【问题标题】:In hive, how to do a calculation among 2 rows?在 hive 中,如何在 2 行之间进行计算?
【发布时间】:2013-05-15 06:42:10
【问题描述】:

我有这张桌子。

   +------------------------------------------------------------+
   |     ks      |      time     |     val1      |    val2      | 
   +-------------+---------------+---------------+--------------+
   |     A       |       1       |       1       |      1       |
   |     B       |       1       |       3       |      5       |
   |     A       |       2       |       6       |      7       |
   |     B       |       2       |      10       |     12       |
   |     A       |       4       |       6       |      7       |
   |     B       |       4       |      20       |     26       |
   +------------------------------------------------------------+

我想要得到的是每一行,

ks |  time |  val1 | val1 of next ts of same ks  |

要清楚,上面例子的结果应该是,

   +------------------------------------------------------------+
   |     ks      |      time     |     val1      |   next.val1  | 
   +-------------+---------------+---------------+--------------+
   |     A       |       1       |       1       |       6      |
   |     B       |       1       |       3       |       10     |
   |     A       |       2       |       6       |       6      |
   |     B       |       2       |      10       |       20     |
   |     A       |       4       |       6       |      null    |
   |     B       |       4       |      20       |      null    |
   +------------------------------------------------------------+

(对于 value2 我也需要同样的下一个)

我尝试了很多方法来为此提出一个配置单元查询,但仍然没有运气。如here(Quassnoi 的回答)所述,我能够在 sql 中为此编写查询,但无法在 hive 中创建等效项,因为 hive 不支持 select 中的子查询。

有人可以帮我实现吗?

提前致谢。

编辑:

我试过的查询是,

SELECT ks, time, val1, next[0] as next.val1 from
(SELECT ks, time, val1
       COALESCE(
       (
       SELECT Val1, time
       FROM myTable mi
       WHERE mi.val1 > m.val1 AND mi.ks = m.ks
       ORDER BY time
       LIMIT 1
       ), CAST(0 AS BIGINT)) AS next
FROM  myTable m
ORDER BY time) t2;

【问题讨论】:

  • 用查询更新了问题。谢谢。
  • 请更新您的问题和示例以反映您在下面提到的附加要求。谢谢。
  • 更新了示例。谢谢。

标签: hive hiveql


【解决方案1】:

您的查询似乎与财务报告中普遍存在的“一年前”报告非常相似。我认为LEFT OUTER JOIN 是您正在寻找的。

我们将表myTable 连接到自身,命名同一个表的两个实例mn。对于第一个表m 中的每个条目,我们将尝试在n 中查找具有相同ks 值但递增值time 的匹配记录。如果此记录不存在,则n 的所有列值都将为NULL

SELECT 
    m.ks, 
    m.time,
    m.val1, 
    n.val1 as next_val1,
    m.val2, 
    n.val2 as next_val2
FROM 
    myTable m
LEFT OUTER JOIN
    myTable n
ON (
    m.ks = n.ks
AND 
    m.time + 1 = n.time
);

返回以下内容。

ks  time  val1  next_val1  val2  next_val2
A   1     1     6          1     7
A   2     6     6          7     7
A   3     6     NULL       7     NULL
B   1     3     10         5     12
B   2     10    20         12    26
B   3     20    NULL       26    NULL

希望对您有所帮助。

【讨论】:

  • 您好 Lukas,感谢您的回复,但我的情况有点不同。很抱歉我的例子误导了你。在这种情况下,时间不一定总是增加 1。它也可以有更大的差距。所以我们不能使用m.time + 1 = n.time。谢谢。
  • 在这种情况下,我建议您使用子查询首先“按 ks,时间”对 myTable 进行排序,然后添加行号。然后,您可以在上面的联接中使用行号,而不是时间。希望对您有所帮助。
  • 我有这个想法,但我找不到添加行号列的方法。下单后能告诉我怎么做吗?
  • Hive 本身不支持行编号,but you could use a UDF to do this
【解决方案2】:

我发现使用 Hive 自定义 map/reduce 功能非常适合解决与此类似的查询。它使您有机会考虑一组输入并“减少”为一个(或多个)结果。

answer 讨论解决方案。

关键是你使用CLUSTER BY将所有key值相似的结果发送到同一个reducer,因此同一个reduce脚本,相应地收集,然后在key发生变化时输出reduced结果,并开始收集新的键。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-20
    • 2013-11-19
    • 1970-01-01
    • 2021-04-16
    • 2018-11-24
    • 1970-01-01
    相关资源
    最近更新 更多