【问题标题】:Hive Sql dynamically get null column counts from a tableHive Sql 从表中动态获取空列计数
【发布时间】:2017-11-19 00:33:10
【问题描述】:

我正在使用 datastax + spark 集成和 spark SQL thrift 服务器,它为我提供了一个 Hive SQL 接口来查询 Cassandra 中的表。

我的数据库中的表是动态创建的,我想做的是仅根据表名获取表的每一列中的空值计数。

我可以使用describe database.table 获取列名,但在 hive SQL 中,我如何在另一个选择查询中使用其输出,该查询对所有列都计数为空。

更新 1:使用 Dudu 的解决方案进行追溯

错误运行查询:TExecuteStatementResp(status=TStatus(errorCode=0, errorMessage="org.apache.spark.sql.AnalysisException: 的无效使用 '*' 在 explode/json_tuple/UDTF;", sqlState=None, infoMessages=["org.apache.hive.service.cli.HiveSQLException:org.apache.spark.sql.AnalysisException: 在 explode/json_tuple/UDTF;:16:15", 中使用无效的 '' 'org.apache.spark.sql.hive.thriftserver.SparkExecuteStatementOperation:org$apache$spark$sql$hive$thriftserver$SparkExecuteStatementOperation$$execute:SparkExecuteStatementOperation.scala:258', 'org.apache.spark.sql.hive.thriftserver.SparkExecuteStatementOperation:runInternal:SparkExecuteStatementOperation.scala:152', 'org.apache.hive.service.cli.operation.Operation:run:Operation.java:257', 'org.apache.hive.service.cli.session.HiveSessionImpl:executeStatementInternal:HiveSessionImpl.java:388', 'org.apache.hive.service.cli.session.HiveSessionImpl:executeStatement:HiveSessionImpl.java:369', 'org.apache.hive.service.cli.CLIService:executeStatement:CLIService.java:262', 'org.apache.hive.service.cli.thrift.ThriftCLIService:ExecuteStatement:ThriftCLIService.java:437', 'org.apache.hive.service.cli.thrift.TCLIService$Processor$ExecuteStatement:getResult:TCLIService.java:1313', 'org.apache.hive.service.cli.thrift.TCLIService$Processor$ExecuteStatement:getResult:TCLIService.java:1298', 'org.apache.thrift.ProcessFunction:process:ProcessFunction.java:39', 'org.apache.thrift.TBaseProcessor:process:TBaseProcessor.java:39', 'org.apache.hive.service.auth.TSetIpAddressProcessor:process:TSetIpAddressProcessor.java:56', 'org.apache.thrift.server.TThreadPoolServer$WorkerProcess:run:TThreadPoolServer.java:286', 'java.util.concurrent.ThreadPoolExecutor:runWorker:ThreadPoolExecutor.java:1142', 'java.util.concurrent.ThreadPoolExecutor$Worker:run:ThreadPoolExecutor.java:617', 'java.lang.Thread:run:Thread.java:745'], statusCode=3), operationHandle=None)

【问题讨论】:

  • 该表是仅包含“原始”数据类型(整数、浮点数、日期等)还是包含复杂数据类型(映射、结构、数组等)?
  • 仅限原始数据类型

标签: hive apache-spark-sql hiveql


【解决方案1】:

在以下解决方案中,无需单独处理每一列。 结果是列索引和该列中空值的数量。
您可以稍后通过列索引将其连接到从元存储中检索到的信息。
一个限制是包含确切文本 null 的字符串将被计为空值。

演示

CTE(mytable 定义为with mytable as)显然可以替换为实际表

with        mytable as 
            (
                select  stack
                        (
                            5
                            
                           ,1   ,1.2     ,date '2017-06-21'     ,null
                           ,2   ,2.3     ,null                  ,null
                           ,3   ,null    ,null                  ,'hello'
                           ,4   ,4.5     ,null                  ,'world'
                           ,5   ,null    ,date '2017-07-22'     ,null
                        ) as (id,amt,dt,txt)
            )

select      pe.pos                                          as col_index
           ,count(case when pe.val='null' then 1 end)       as nulls_count

from        mytable t lateral view posexplode (split(printf(concat('%s',repeat('\u0001%s',field(unhex(1),t.*,unhex(1))-2)),t.*),'\\x01')) pe

group by    pe.pos       
;

+-----------+-------------+
| col_index | nulls_count |
+-----------+-------------+
|         0 |           0 |
|         1 |           2 |
|         2 |           3 |
|         3 |           3 |
+-----------+-------------+

【讨论】:

  • 我添加了运行查询时遇到的错误的回溯
  • 这是在 Hive 上测试的。似乎 Spark 不喜欢 posexplode* 的组合
【解决方案2】:

您可以使用

代替描述database.table

Select column_name from system_schema.columns where keyspace_name='YOUR KEYSPACE' and table_name='YOUR TABLE'

上表中还有一个名为kind的列,其值类似于partition_key,clustering,regular

值为partition_keyclustering 的列不会有空值。

对于您可以使用的其他列

select sum(CASE WHEN col1 is NULL THEN 1 ELSE 0 END) as col1_cnt,sum(CASE WHEN col2 is NULL THEN 1 ELSE 0 END) as col2_cnt from table1 where col1 is null;

你也可以试试下面的查询(我自己没试过)

SELECT COUNT(*)-COUNT(col1) As A, COUNT(*)-COUNT(col2) As B, COUNT(*)-COUNT(col3) As C
FROM YourTable; 

可能对于上述查询,您可以每次都为 count 创建变量而不是 count(*)。

注意:system_schema.columns 是 cassandra 表,cassandra 用户应具有该表的读取权限

【讨论】:

  • 我不想硬编码列名,因为我有数百个表
  • 您不必对其进行硬编码...从Select column_name from system_schema.columns where keyspace_name='YOUR KEYSPACE' and table_name='YOUR TABLE' 读取并制作您的选择子句...
  • 是的,我如何在不使用脚本语言而只使用 hive SQL 的情况下创建 select 子句,这就是问题所在,我已经有了使用 describe database.table 的列名
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-20
相关资源
最近更新 更多