为什么两个非常相似的Hive查询返回不同的结果(其中之一显然是错误的)?

时间:2019-05-28 07:54:13

标签: sql hive

所以我有一个奇怪的情况,其中两个非常相似的查询返回不同的结果。第一个查询是这样的:

select src.period_num period_num,
src.flag flag,
src.week_num week_num,
((src.year_num * 100) + src.period_num) year_num,
count(distinct src.id) result_count
from src_table src
group by src.period_num,
src.flag,
src.week_num,
((src.year_num * 100) + src.period_num)

第二个查询是这个查询:

select src.period_num period_num,
src.flag flag,
src.week_num week_num,
((src.year_num * 100) | src.period_num) year_num,
count(distinct src.id) result_count
from src_table src
group by src.period_num,
src.flag,
src.week_num,
((src.year_num * 100) | src.period_num)

如您所见,查询只有一个区别-在第一个查询中,我们使用加法(+),在第二个查询中,我们使用按位OR(|) 我的问题是,对于第一个结果,我们会收到类似的结果(我只留下了大部分):

+-------------+---------+-----------+-----------+---------------+--+
| period_num  | flag    | week_num  | year_num  | result_count  |
+-------------+---------+-----------+-----------+---------------+--+
| 6           | true    | 21        | 201906    | 94            |

而第二个返回此:

+-------------+---------+-----------+-----------+---------------+--+
| period_num  | flag    | week_num  | year_num  | result_count  |
+-------------+---------+-----------+-----------+---------------+--+
| 6           | true    | 21        | 201902    | 87            |
| 6           | false   | 21        | 201902    | 7             |

第二个结果计数是正确的,带有正确的按标志分组,但是您可以看到现在year_num变得混乱了。无论如何,我的主要问题是我无法理解第一个查询到底出了什么问题,因为它似乎并没有带来什么问题。 任何想法和帮助,表示赞赏。

1 个答案:

答案 0 :(得分:0)

按位或与加法完全不同的操作。因此,它将产生完全不同的结果。

请考虑以下两个二进制“操作”示例。

第一次加法(1 + 3 = 4):

  0001
+ 0011
  ----
= 0100

和按位或(1 | 3 = 3):

  0001
+ 0011
  ----
= 0011

我希望这可以帮助您解决问题。

哦,请记住,将数字乘以100会在基数10(十进制)中引入两个尾随零,但是在二进制中,最低有效位上仍可能设置位。

例如,201900以二进制形式110001010010101100

在没有更多细节的情况下,很难解释为什么简单地通过按位或加法将src.flag神奇地从false更改为true。准备您的示例,是否有可能不小心更改了其他内容?

按照承诺,我已经通过Spark-SQL运行您的示例数据。我将您的数据集减少为仅94条记录,其中year_num = 2019和period_num = 6。

这是运行的结果,显示为两个查询生成相同的答案。接下来就是整个过程,如果您可以使用spark-shell,可以尝试一下。蜂巢中可能有一个错误,但我不会从这个假设开始。

scala> val sumDF=sql("""select src.period_num period_num,
     |   src.flag flag,                                                                                                                                                                                           
     |   src.week_num week_num,                                                                                                                                                                                   
     |   ((src.year_num * 100) + src.period_num) year_num,                                                                                                                                                        
     |   count(distinct src.id) result_count                                                                                                                                                                      
     |   from src_table src                                                                                                                                                                                       
     |   group by src.period_num,                                                                                                                                                                                 
     |   src.flag,                                                                                                                                                                                                
     |   src.week_num,                                                                                                                                                                                            
     |   ((src.year_num * 100) + src.period_num)                                                                                                                                                                  
     |   """)
sumDF: org.apache.spark.sql.DataFrame = [period_num: int, flag: boolean ... 3 more fields]

scala> sumDF.show
+----------+-----+--------+--------+------------+
|period_num| flag|week_num|year_num|result_count|
+----------+-----+--------+--------+------------+
|         6|false|      21|  201906|           7|
|         6| true|      21|  201906|          87|
+----------+-----+--------+--------+------------+

scala> val orDF=sql ("""select src.period_num period_num,
     |   src.flag flag,
     |   src.week_num week_num,
     |   ((src.year_num * 100) | src.period_num) year_num,
     |   count(distinct src.id) result_count
     |   from src_table src
     |   group by src.period_num,
     |   src.flag,
     |   src.week_num,
     |   ((src.year_num * 100) | src.period_num)
     |   """)
orDF: org.apache.spark.sql.DataFrame = [period_num: int, flag: boolean ... 3 more fields]

scala> orDF.show
+----------+-----+--------+--------+------------+
|period_num| flag|week_num|year_num|result_count|
+----------+-----+--------+--------+------------+
|         6| true|      21|  201902|          87|
|         6|false|      21|  201902|           7|
+----------+-----+--------+--------+------------+

这是完整的工作:

var dataDF=spark.read.option("header","true").option("inferSchema","true").csv("source_data_from_op_2019_06.csv")
dataDF.printSchema
dataDF.count                                                                                                                                                                                 
dataDF.show

dataDF.createOrReplaceTempView("src_table")


val sumDF=sql("""select src.period_num period_num,
  src.flag flag,
  src.week_num week_num,
  ((src.year_num * 100) + src.period_num) year_num,
  count(distinct src.id) result_count
  from src_table src
  group by src.period_num,
  src.flag,
  src.week_num,
  ((src.year_num * 100) + src.period_num)
  """)

sumDF.show

val orDF=sql ("""select src.period_num period_num,
  src.flag flag,
  src.week_num week_num,
  ((src.year_num * 100) | src.period_num) year_num,
  count(distinct src.id) result_count
  from src_table src
  group by src.period_num,
  src.flag,
  src.week_num,
  ((src.year_num * 100) | src.period_num)
  """)
orDF.show

您可以在Spark-shell中尝试吗?