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

ecbunoof  于 2021-06-24  发布在  Hive
关注(0)|答案(1)|浏览(235)

所以我有一个奇怪的例子,两个非常相似的查询返回不同的结果。第一个查询是:

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\u num搞砸了。不管怎么说,我的主要问题是,我无法理解第一个查询到底出了什么问题,因为它似乎没有什么根本不好的地方。任何想法和帮助都将不胜感激。

nc1teljy

nc1teljy1#

按位“或”是与加法完全不同的操作。因此,它将产生完全不同的结果。
考虑下面两个二进制“操作”的例子。
第一次加法(1+3=4):

0001
+ 0011
  ----
= 0100

和位或(1 | 3=3):

0001
+ 0011
  ----
= 0011

我希望这对你的问题有帮助。
哦,记住,将一个数字乘以100将引入以10为底的两个尾随零(十进制),但在二进制中,仍然可以将位设置为最低有效位。
例如,201900是 110001010010101100 二进制的。
如果没有更多的细节,很难解释为什么src.flag仅仅通过使用按位or而不是加法就可以神奇地从false变为true。有没有可能在准备你的例子时,你不小心改变了其他的东西?
正如我所承诺的,我已经通过sparksql运行了您的示例数据。我将您的数据集缩减为仅包含年份为2019、期间为6的94条记录。
下面是运行的结果,显示了为两个查询生成的相同答案。接下来是整个序列,你可以尝试自己,如果你有权访问Spark壳。有可能 hive 里有虫子,但我不会从这个假设开始。

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里试试这个吗?

相关问题