Hive查询生成与条件匹配的行序列的标识符

时间:2015-06-02 15:38:23

标签: hadoop hive windowing

我们说我有以下的hive表作为输入,让我们称之为connections

userid  | timestamp   
--------|-------------
1       | 1433258019  
1       | 1433258020
2       | 1433258080
2       | 1433258083
2       | 1433258088
2       | 1433258170
[...]   | [...]

使用以下查询:

SELECT
    userid,
    timestamp,
    timestamp - LAG(timestamp, 1, 0) OVER w AS timediff
    CASE
      WHEN timediff > 60
      THEN 'new_session'
      ELSE 'same_session'
    END AS session_state
FROM connections
WINDOW w PARTITION BY userid ORDER BY timestamp ASC;

我生成以下输出:

userid  | timestamp   | timediff   | session_state
--------|-------------|------------|---------------
1       | 1433258019  | 1433258019 | new_session
1       | 1433258020  | 1          | same_session
2       | 1433258080  | 1433258080 | new_session
2       | 1433258083  | 3          | same_session
2       | 1433258088  | 5          | same_session
2       | 1433258170  | 82         | new_session
[...]   | [...]       | [...]      | [...]

如何生成:

userid  | timestamp   | timediff   | sessionid
--------|-------------|------------------------------
1       | 1433258019  | 1433258019 | user1-session-1
1       | 1433258020  | 1          | user1-session-1
2       | 1433258080  | 1433258080 | user2-session-1
2       | 1433258083  | 3          | user2-session-1
2       | 1433258088  | 5          | user2-session-1
2       | 1433258170  | 82         | user2-session-2
[...]   | [...]       | [...]      | [...]

这是否可能只使用HQL和#34;着名" UDF(我不想使用自定义UDF或reducer脚本)?

3 个答案:

答案 0 :(得分:2)

有趣的问题。根据您对@Madhu的评论,我在您的示例中添加了行2 1433258172。您需要的是每次timediff > 60满足时增加。最简单的方法是标记它,然后累计在窗口上求和。

<强>查询:

select userid
  , timestamp
  , concat('user', userid, '-session-', s_sum) sessionid
from (
  select *
    , sum( counter ) over (partition by userid
                           order by timestamp asc
                           rows between unbounded preceding and current row) s_sum
  from (
    select *
      , case when timediff > 60 then 1 else 0 end as counter
    from (
      select userid
        , timestamp
        , timestamp - lag(timestamp, 1, 0) over (partition by userid
                                                 order by timestamp asc) timediff
      from connections ) x ) y ) z

<强>输出:

1   1433258019  user1-session-1
1   1433258020  user1-session-1
2   1433258080  user2-session-1
2   1433258083  user2-session-1
2   1433258088  user2-session-1
2   1433258170  user2-session-2
2   1433258172  user2-session-2

答案 1 :(得分:0)

使用以下内容 从员工中选择concat_ws(&#39; - &#39;,名称,城市); concat_ws的第一个参数是separator。 name和city是employee表的列名。看到它们是字符串类型。您可以查看here了解更多

答案 2 :(得分:0)

这有效:

SELECT 
  userid,
  timestamp,
  timediff,
  CONCAT(
    'user',
     userid,
     '-',
     'session-',
     CAST(timediff / 60 AS INT) + 1
  ) AS session_id
  FROM (
    SELECT   
      userid,
      timestamp,
      timestamp - LAG(timestamp, 1, timestamp) OVER w AS timediff
    FROM connections
    WINDOW w AS (
      PARTITION BY userid
      ORDER BY timestamp ASC
    )
) a;

输出:

userid  timestamp   timediff    session_state
1       1433258019  0.0         user1-session-1
1       1433258020  1.0         user1-session-1
2       1433258080  0.0         user2-session-1
2       1433258083  3.0         user2-session-1
2       1433258088  5.0         user2-session-1
2       1433258170  82.0        user2-session-2
3       1433258270  0.0         user3-session-1

如果不需要timediff,你可以尝试这样的事情:

选择userid,timestamp,session_count + concat('user',userid,' - ','session - ',cast(LAG(session_count-1,1,0)在w1上作为字符串))AS session_state
- 通过w1 AS session_count_new的LAG(session_count-1,1,0) 从 (选择      用户身份,      时间戳,      timeDiff测量, cast(timediff / 60 as int)+1作为session_count