获取Hive查询中分区组的最后一个值,但有其他要求

时间:2017-03-15 13:01:49

标签: sql hive hiveql

说我在表中有3列:id,flag,time。标志只能是三个中的一个:A1,A2,B。

ID  flag    time
1   A1  2016-01-01
1   A2  2016-01-02
1   B   2016-01-03
1   B   2016-01-04
2   A1  2016-01-02
2   B   2016-01-03
2   A2  2016-01-04
2   B   2016-01-05

每个ID的数据都按时间排序。现在,我希望得到每个ID,当标志等于B时,最后一个非B标志,例如:

1   B   2016-01-03  A2  2016-01-02
1   B   2016-01-04  A2  2016-01-02
2   B   2016-01-03  A1  2016-01-02
2   B   2016-01-05  A2  2016-01-04

这在Hive查询中是否可行?尝试使用ROW_NUMBERLAST_VALUE,但无法找到完美的解决方案。

更新: 两个答案都有效。我第一次知道case可以在max中使用 MessageQueue rmTxnQ = new MessageQueue("FormatName:Direct=TCP:IP\\private$\\queuename"); rmTxnQ.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) }); System.Messaging.Message msgTxn = rmTxnQ.Receive(MessageQueueTransactionType.Single); MessageBox.Show(msgTxn.Body.ToString()); 。浪费了很多时间来解决这个问题。

2 个答案:

答案 0 :(得分:1)

使用max窗口函数获取非B标志的运行最长时间。然后join将此结果发送到原始表,以获取相应最大时间的标志信息(在给定id的标志B之前)。

SELECT X.*,
       T.FLAG
FROM
 (SELECT T.*,
  MAX(CASE WHEN FLAG<>'B' THEN TIME END) OVER(PARTITION BY ID ORDER BY TIME) AS MAX_TIME_BEFORE_B
  FROM T
 ) X
JOIN T ON T.ID=X.ID AND T.TIME=X.MAX_TIME_BEFORE_B
WHERE X.FLAG='B'

Sample Demo

答案 1 :(得分:1)

select  id
       ,flag
       ,time
       ,A.flag as A_flag
       ,A.time as A_time

from   (select  id
               ,flag
               ,time

               ,max
                (
                    case 
                        when flag <> 'B' 
                        then named_struct ('time',time,'flag',flag) 
                    end
                ) over
                (   
                    partition by    id 
                    order by        time 
                    rows            unbounded preceding
                )  as A

        from    t
        ) t

where   flag = 'B'
;
+----+------+------------+--------+------------+
| id | flag |    time    | a_flag |   a_time   |
+----+------+------------+--------+------------+
|  1 | B    | 2016-01-03 | A2     | 2016-01-02 |
|  1 | B    | 2016-01-04 | A2     | 2016-01-02 |
|  2 | B    | 2016-01-03 | A1     | 2016-01-02 |
|  2 | B    | 2016-01-05 | A2     | 2016-01-04 |
+----+------+------------+--------+------------+

P.S。

  • 我建议不要使用可能是保留字(time)作为列名。
  • 我建议不要将time等不需要的名称用于日期列。