如何从Spark SQL Query[PySpark]获取表名?

2024-06-08 00:26:46 发布

您现在位置:Python中文网/ 问答频道 /正文

要从SQL查询中获取表名

select *
from table1 as t1
full outer join table2 as t2
  on t1.id = t2.id

我在Scala中找到了一个解决方案How to get table names from SQL query?

^{pr2}$

当我迭代返回序列getTables(query).foreach(println)时,它给出了正确的表名

table1
table2

PySpark的等效语法是什么?我遇到的最接近的是 How to extract column name and column type from SQL in pyspark

plan = spark_session._jsparkSession.sessionState().sqlParser().parsePlan(query)
print(f"table: {plan.tableDesc().identifier().table()}")

回溯失败了

Py4JError: An error occurred while calling o78.tableDesc. Trace:
py4j.Py4JException: Method tableDesc([]) does not exist
    at py4j.reflection.ReflectionEngine.getMethod(ReflectionEngine.java:318)
    at py4j.reflection.ReflectionEngine.getMethod(ReflectionEngine.java:326)
    at py4j.Gateway.invoke(Gateway.java:274)
    at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:132)
    at py4j.commands.CallCommand.execute(CallCommand.java:79)
    at py4j.GatewayConnection.run(GatewayConnection.java:238)
    at java.base/java.lang.Thread.run(Thread.java:835)

I understand, the problem stems up from the fact that I need to filter all plan items which are of type UnresolvedRelation but I cannot find an equivalent notation in python/pyspark


Tags: tofromsqlastablejavaqueryat
1条回答
网友
1楼 · 发布于 2024-06-08 00:26:46

我有办法,但相当复杂。它转储Java对象和JSON(穷人的序列化过程),将其反序列化为python对象,过滤和解析表名

import json
def get_tables(query: str):
    plan = spark._jsparkSession.sessionState().sqlParser().parsePlan(query)
    plan_items = json.loads(plan.toJSON())
    for plan_item in plan_items:
        if plan_item['class'] == 'org.apache.spark.sql.catalyst.analysis.UnresolvedRelation':
            yield plan_item['tableIdentifier']['table']

当我迭代函数list(get_tables(query))时,会产生['fast_track_gv_nexus', 'buybox_gv_nexus']

注意不幸的是,CTE

示例

^{pr2}$

为了解决这个问题,我必须通过正则表达式来破解

import json
import re
def get_tables(query: str):
    plan = spark._jsparkSession.sessionState().sqlParser().parsePlan(query)
    plan_items = json.loads(plan.toJSON())
    plan_string = plan.toString()
    cte = re.findall(r"CTE \[(.*?)\]", plan_string)
    for plan_item in plan_items:
        if plan_item['class'] == 'org.apache.spark.sql.catalyst.analysis.UnresolvedRelation':
            tableIdentifier = plan_item['tableIdentifier']
            table =  plan_item['tableIdentifier']['table']   
            database =  tableIdentifier.get('database', '')
            table_name = "{}.{}".format(database, table) if database else table
            if table_name not in cte:
                yield table_name

相关问题 更多 >

    热门问题