【问题标题】:Python, dataframe sql joinPython,数据框sql连接
【发布时间】:2019-05-03 14:07:32
【问题描述】:

我有两个直接查询数据库的 python 函数。 有没有办法在 python 中加入这两个函数?

我想做几个连接,但不确定如何在 python 中完成。

查询 1:

def query1(businessDate):
    con = pyodbc.connect(r'DSN='+'Stack',autocommit=True)  
    print('working')
    #businessDate = r"'2019-03-13'"
    #remember business date should be entered like "'2019-03-13'"

    sql = f"""

     SELECT 
       iddate, 
       businessdate, 
       stack, identifier
     FROM stackoverflow
     where stack is not null 
     and businessdate = {businessDate}

    """

    df_stack = pd.read_sql(sql,con)

    con.close()

    return(df_stack)

查询 2:

    def superuser(businessDate):  
    con = pyodbc.connect(r'DSN='+'super',autocommit=True)  
    print('working')
    #remember business date should be entered like "'2019-03-13'"

    sql = f"""
    SELECT 
      iddate,
      businessdate,
      stack, identifier
    FROM superuser
    WHERE stack is not null 
    and businessdate = {businessDate}


    """

    df_super = pd.read_sql(sql,con)

    con.close()

    return(df_super)

我想在identifierstackiddatebusinessdate 上对表 2 进行左外联接

尝试:

def testjoin():
    con = pyodbc.connect(r'DSN='+'Stack',autocommit=True)  
    print('working') 

    pd.merge(df_stack,df_super, on = ['identifier','stack','iddate'])

    df_test = pd.read_sql(sql,con)

    con.close()

    return(df_test)

尝试2:

def testjoin():
    con = pyodbc.connect(r'DSN='+'Stack',autocommit=True)  
    print('working') 

    df_stack= query1("'2019-03-13'")
    df_super= superuser("'2019-03-13'")

    pd.merge(df_stack,df_super, on = ['identifier','stack','iddate'])

    df_test = pd.read_sql(sql,con)

    con.close()

    return(df_test)

收到错误name 'sql' is not defined'

【问题讨论】:

    标签: python-3.x


    【解决方案1】:

    左外连接

    SELECT *
    FROM df_stack
    LEFT OUTER JOIN df_super
        ON df_stack.stack = df_super.stack
        ON df_stack.identifier= df_super.identifier 
        ON df_stack.iddate = df_super.iddate
        ON df_stack.businessdate = df_super.businessdate;
    
    pd.merge(df_stack,df_super,
             on=['iddate','businessdate', 'stack', 'identifier'], 
             how='left')
    

    【讨论】:

    • 当我调用我的 testjoin 函数时,我得到 df_stack 未定义。我做错了什么? NameError: name 'df_stack' is not defined
    • 除非df_stack 是一个全局变量,否则它不会在testjoin() 函数的范围内,除非您将它作为参数传递
    • 为了PEP8,为了我的眼睛,在不需要的时候请不要使用`\`来续行。 (括号、方括号和大括号中不需要):)
    • @excelguy 尝试,将df_stack 替换为query1(),并将df_super 替换为query2() 函数定义中的query2()
    • @MatthewBarlowe 我该怎么做?我在同一个 .py 文件中拥有所有这些功能。
    【解决方案2】:

    好的,我将把它作为答案而不是 cmets 发布,因为有几种方法可以满足您的要求。 sql 没有像我在评论中指出的那样定义,因为它超出了函数 testjoin() 的范围。

    一种方法是将 SQL 字符串视为全局变量,然后在函数内部访问它。

    sql = '''
      SELECT 
        iddate, 
        businessdate, 
        stack, identifier
      FROM stackoverflow
      where stack is not null 
      and businessdate = {businessDate}
    '''
    
    def testjoin():
        con = pyodbc.connect(r'DSN='+'Stack',autocommit=True)  
        print('working') 
    
        df_stack= query1("'2019-03-13'")
        df_super= superuser("'2019-03-13'")
    
        pd.merge(df_stack,df_super, on = ['identifier','stack','iddate'])
    
        df_test = pd.read_sql(sql.format(businessDate="'2019-03-14'"),con)
    
        con.close()
    
        return(df_test)
    

    我使用.format() 而不是f 字符串的原因是f 字符串需要在创建f 字符串时声明变量。如果您没有 businessdate 作为变量,那将是一个错误。 .format() 允许您将变量放在字符串中,然后随时更改它的值。如果您的查询的主要部分不会发生太大变化并且您只需要按日期过滤,我会这样做。

    另一种方法是在函数外部构建字符串,然后将其作为参数传入

    businessdate = "'2019-03-13'"
    sql = f'''
      SELECT 
        iddate, 
        businessdate, 
        stack, identifier
      FROM stackoverflow
      where stack is not null 
      and businessdate = {businessDate}
    '''
    
    def testjoin(sql_string):
        con = pyodbc.connect(r'DSN='+'Stack',autocommit=True)  
        print('working') 
    
        df_stack= query1("'2019-03-13'")
        df_super= superuser("'2019-03-13'")
    
        pd.merge(df_stack,df_super, on = ['identifier','stack','iddate'])
    
        df_test = pd.read_sql(sql_string,con)
    
        con.close()
    
        return(df_test)
    
    test_df = testjoin(sql)
    

    您也可以继续在每个函数中构建字符串,但考虑到编码中的Don't Repeat Yourself paradigm,并且您已经在其他两个函数中构建它,最好避免这种情况。

    【讨论】:

    • 啊我现在明白了,谢谢。但是如果我有 2 个 sql 查询呢?最好做第二个选项并将sql字符串变成2个参数吗?
    • 这真的取决于。关于这一点没有硬性规定,我知道有人可以纠正我,如果他们知道的话。但最终归结为您将如何在代码中使用它。由于超出此问题范围的原因,通常全局变量被视为somewhat bad in OOP programming。这只是随着时间和编码和阅读他人代码的经验而来的东西
    • 感谢您的所有帮助,matthew,我无法调用 2 个 Sql 查询,因为我不确定如何在 df_test 变量中调用它。我会做2个变量吗?但那我会返回哪一个呢?还有一个随机问题test_df = testjoin(sql) 是做什么的?
    • test_df = testjoin(sql)testjoin() 函数的返回值分配给一个变量,以便您以后可以在脚本中使用它。如果您需要调用两个查询,那么您需要有两个单独的 SQL 字符串并调用 pd.read_sql 两次
    猜你喜欢
    • 1970-01-01
    • 2021-11-09
    • 1970-01-01
    • 2021-07-20
    • 2018-01-12
    • 2018-02-01
    • 1970-01-01
    • 2022-07-11
    • 2017-02-25
    相关资源
    最近更新 更多