【问题标题】:Reduction in the number of records using range join使用范围连接减少记录数
【发布时间】:2017-06-07 04:26:28
【问题描述】:

关注my question 我有以下表格,第一个(范围)包括值范围和附加列:

row  | From   |  To     | Country ....
-----|--------|---------|---------
1    | 1200   |   1500  |
2    | 2200   |   2700  |
3    | 1700   |   1900  |
4    | 2100   |   2150  |
... 

FromTo 是 bigint 并且是独占的。 Range 表包含 180 万条记录。附加表(值)包含 270 万条记录,如下所示:

 row     | Value  | More columns....
 --------|--------|----------------
    1    | 1777   |    
    2    | 2122   |    
    3    | 1832   |    
    4    | 1340   |    
    ... 

我想创建一个如下表:

row      | Value  | From   | To    | More columns....
 --------|--------|--------|-------|---
    1    | 1777   | 1700   | 1900  |
    2    | 2122   | 2100   | 2150  |   
    3    | 1832   | 1700   | 1900  |   
    4    | 1340   | 1200   | 1500  |   
    ... 

我在以下代码中使用了左外连接:

set n=1000;

select      v.id
           ,v.val
           ,r.from_val
           ,r.to_val

from      val v
        left outer join    

 (select  r.*
                   ,floor(from_val/${hiveconf:n}) + pe.i    as match_val

            from    val_range r
                    lateral view    posexplode
                                    (
                                        split
                                        (
                                            space
                                            (
                                                cast
                                                (
                                                    floor(to_val/${hiveconf:n}) 
                                                  - floor(from_val/${hiveconf:n}) 

                                                    as int
                                                )
                                            )
                                           ,' '
                                        )
                                    ) pe as i,x
            ) r



            on      floor(v.val/${hiveconf:n})    =
                    r.match_val

where       v.val between r.from_val and r.to_val

order by    v.id       
;

但是,新表的记录数量大幅减少,大约 270 万条记录中的 31000 条记录。如果我使用left outer join 会怎样?我该如何解决?

【问题讨论】:

  • 早上好 Avi :-) r (v.val between r.from_val and r.to_val) 上有一个过滤器,它实际上取消了 LEFT JOIN 的功能并将其转换为 INNER JOIN 显然并非所有值都是被范围覆盖。
  • 非常感谢!如何使用 Left Join 的功能?之间是必不可少的,因为它确定了相关值的所需范围?我不想省略没有范围的值。
  • 我假设 v.id 是唯一的?
  • 实际上没有 v.id 那么我们可以使用行号作为唯一键吗?
  • 它适用于相对较小的数据集。对于大型集,请查看stackoverflow.com/questions/42974548/…

标签: join hive left-join between impala


【解决方案1】:

假设我们有一个v.id

set n=1000;

select      v.id
           ,r.from_val
           ,r.to_val

from                    val     v 

            left join  (select      v.id
                                   ,r.from_val
                                   ,r.to_val

                        from                val     v 

                                    join    (...)   r 

                                    on      floor(v.val/${hiveconf:n})    =
                                            r.match_val

                        where       v.val between r.from_val and r.to_val
                        ) r

            on          r.id    =
                        v.id

order by    v.id       

关于 OP 请求,这里是完整的查询:

set n=1000;

select      v.id
           ,r.from_val
           ,r.to_val

from                    val     v 

            left join  (select      v.id
                                   ,r.from_val
                                   ,r.to_val

                        from                val     v 

                                    join   (select  r.*
                                                   ,floor(from_val/${hiveconf:n}) + pe.i    as match_val

                                            from    val_range r
                                                    lateral view    posexplode
                                                                    (
                                                                        split
                                                                        (
                                                                            space
                                                                            (
                                                                                cast
                                                                                (
                                                                                    floor(to_val/${hiveconf:n}) 
                                                                                  - floor(from_val/${hiveconf:n}) 

                                                                                    as int
                                                                                )
                                                                            )
                                                                           ,' '
                                                                        )
                                                                    ) pe as i,x
                                            ) r

                                    on      floor(v.val/${hiveconf:n})    =
                                            r.match_val

                        where       v.val between r.from_val and r.to_val
                        ) r

            on          r.id    =
                        v.id

order by    v.id       

【讨论】:

  • 亲爱的@Dudu Markovitz,请您填写加入(...)。我认为 r 有两个别名。另外,能否请您解释一下为什么要添加 r.id = v.id?因为即使我将行号添加为每个表的唯一 ID,它们也不应该相等?非常感谢。
  • 已添加。在不同范围内重用别名没有问题。 r.id实际上是v.id在一个以r为别名的子查询中
猜你喜欢
  • 2014-07-16
  • 2014-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-07
  • 2011-12-30
相关资源
最近更新 更多