【问题标题】:Python SQL loop variables through multiple queriesPython SQL 通过多个查询循环变量
【发布时间】:2020-06-05 12:12:18
【问题描述】:

我在使用 Python Teradata (tdodbc) 查询时遇到问题,该查询循环使用不同变量的同一查询并合并结果。我在另一个post 收到了很好的指导并最终来到了这里。我现在的问题是数据框仅以循环中最终变量“state5”的查询结果结束。不幸的是,我们在各自的数据库中有 5 个状态,每个状态具有相同的模式。我可以运行相同的查询,但想要循环变量,以便我可以针对所有 5 个状态运行并返回附加的查询。这很容易使用 SAS 宏变量和修复,但需要将数据带到 Python 中以进行 EDA 和数据科学。

from teradata import tdodbc
udaExec = td.UdaExec(appConfigFile="udaexec.ini")
with udaExec.connect("${dataSourceName}") as session:


    state_dataframes = []
    STATES = ["state1", "state2", "state3", "state4", "state5"]

    for state in STATES:

    query1 = """database my_db_{};"""

    query2 = """      
        select top 10
        '{}' as state
        ,a.*
        from table_a
        """

    session.execute(query1.format(state))
    session.execute(query2.format(state))

    state_dataframes.append(pd.read_sql(query2, session))
    all_states_df = pd.concat(state_dataframes)

【问题讨论】:

  • 似乎不是做一个单独的session.execute(query2.format(state)),你想把.format(state)放在read_sql里面。还将for 循环体缩进到append,并将concatfor 保持在同一级别。您还可以消除数据框列表,并将 append 每个 read_sql 删除到结果数据框。
  • 谢谢你,弗雷德!我是熊猫和python的初学者。你能告诉我关于消除数据框的最后建议的代码吗?
  • 如果我使用易失性表并循环显示易失性表已在使用的位置,我也会遇到问题。似乎我需要在每个循环后关闭连接?
  • 你不必关闭连接;您可以显式地 DROP 易失性表或只是 DELETE 每次迭代的内容。或者更好的是,您还可以在 volatile 表中累积数据,然后执行 read_sql 将其放入数据帧;这可能是总体上最快的。我现在想到 DataFrame.append 不会就地发生,所以 state_dataframes 列表末尾有一个 append 可能会更好。但为了完整起见:我们的想法是从一个空数据框开始,并让每次迭代都执行df = df.append(pd.read_sql(query2.format(state), session))
  • 谢谢@Fred。在 DDL 错误后,我在删除表和接收 ET 或 Null 时遇到问题。我能够修复它并将发布答案。

标签: python sql pandas for-loop teradata


【解决方案1】:

尽管这可能不是最有说服力的方法,但我终于能够让它发挥作用。我确实尝试将删除表作为单个变量“query5”执行,但收到​​ DDL 错误。一旦我将每个放置表分离到它自己的 session.execute 中,它就起作用了。

udaExec = td.UdaExec(appConfigFile="udaexec.ini")

with udaExec.connect("${dataSourceName}") as session:

    state_dataframes = []
    STATES = ["state1", "state2", "state3", "state4", "state5"]

    for state in STATES:

            query1 = """database my_db_{};"""

            query2 = """   
            create set volatile table v_table
            ,no fallback, no before journal, no after journal as
            (  
            select top 10
            '{}' as state
            ,t.*
            from table t
            )   
            with data
            primary index (dw_key)  
            on commit preserve rows;
            """

            query3 = """
            create set volatile table v_table_2
            ,no fallback, no before journal, no after journal as
            (  
            select t.*
            from v_table t
            )   
            with data
            primary index (dw_key)  
            on commit preserve rows;

            """

            query4 = """

            select t.* 
            from v_table_2 t

            """

            session.execute(query1.format(state))
            session.execute(query2.format(state))
            session.execute(query3)
            state_dataframes.append(pd.read_sql(query4, session))
            session.execute("DROP TABLE v_table")
            session.execute("DROP TABLE v_table_2")

    all_states_df = pd.concat(state_dataframes)

为清楚起见进行编辑:更正问题中的查询只需要适当的缩进。在我的 Teradata 环境中,我的假脱机空间有限,这需要构建许多 vol 表来分解查询。由于我花了很多时间试图解决这个问题,所以我添加了答案以帮助可能遇到这种情况的其他人。

【讨论】:

  • 好的。是的,DROP 必须自己执行。您不需要session.execute(query4),因为它无论如何都是作为read_sql 的一部分运行的。在这个(可能是“清理过的”)示例中,无需将一个易失性表复制到另一个具有不同主索引的表。
  • 我不熟悉 Teradata,但请向当前和未来的读者解释使用易失性表的必要性。 for 循环的正确缩进不能解决您上面的原始问题吗?
  • 你是对的。我添加了 vol 表,因为某些用户可能有假脱机空间限制并且需要分解 teradata 中的查询。我花了很多时间解决这个问题,所以认为这对其他人会有所帮助。第一个查询将使用适当的缩进。为了清楚起见,我将编辑答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-01
  • 1970-01-01
  • 2016-10-16
  • 2012-05-23
  • 2020-10-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多