说我在表中有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_NUMBER
和LAST_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());
。浪费了很多时间来解决这个问题。
答案 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'
答案 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
等不需要的名称用于日期列。