如何将SQL查询结果转换为PANDAS数据结构?

161 人关注

如果对这个问题有任何帮助,我们将不胜感激。

所以基本上我想在我的SQL数据库中运行一个查询,并将返回的数据存储为Pandas数据结构。

我已经附上了查询的代码。

我正在阅读Pandas的文档,但我在识别查询的返回类型方面遇到了问题。

我试图打印查询结果,但它没有提供任何有用的信息。

谢谢!!!!

from sqlalchemy import create_engine
engine2 = create_engine('mysql://THE DATABASE I AM ACCESSING')
connection2 = engine2.connect()
dataid = 1022
resoverall = connection2.execute("
    SELECT 
       sum(BLABLA) AS BLA,
       sum(BLABLABLA2) AS BLABLABLA2,
       sum(SOME_INT) AS SOME_INT,
       sum(SOME_INT2) AS SOME_INT2,
       100*sum(SOME_INT2)/sum(SOME_INT) AS ctr,
       sum(SOME_INT2)/sum(SOME_INT) AS cpc
    FROM daily_report_cooked
    WHERE campaign_id = '%s'",
    %dataid

所以我想了解我的变量 "resoverall "的格式/数据类型是什么,以及如何把它放在PANDAS数据结构中。

python
mysql
data-structures
pandas
user1613017
user1613017
发布于 2012-08-21
18 个回答
Daniel
Daniel
发布于 2021-02-13
已采纳
0 人赞同

这里有最短的代码,可以完成这项工作。

from pandas import DataFrame
df = DataFrame(resoverall.fetchall())
df.columns = resoverall.keys()

你可以像保罗的回答那样,更大胆地去解析类型。

这对我来说是有效的,因为我从一个Oracle数据库中发现了1.000.000条记录。
df = DataFrame(cursor.fetchall()) 返回 ValueError: DataFrame constructor not properly called! ,看来tuple of tuple对于DataFrame构造函数来说是不可接受的。在字典或元组模式下,游标上也没有 .keys()
只需注意,keys方法只对使用sqlalchemy获得的结果有效。Pyodbc对列使用描述属性。
这对Postgres数据库有用吗?我试图用 keys() 函数来获取结果数据框的列名,但无法成功。
@BowenLiu 是的,你可以用psycopg2 df.columns=[ x.name for x in recoverall.description ]
beardc
beardc
发布于 2021-02-13
0 人赞同

编辑:Mar.2015

如下所述,pandas现在使用 SQLAlchemy 读取( read_sql )并插入到( to_sql )一个数据库。下面的方法应该可行

import pandas as pd
df = pd.read_sql(sql, cnxn)

前一个答案。 通过mikebmassey从一个类似问题

import pyodbc
import pandas.io.sql as psql
cnxn = pyodbc.connect(connection_info) 
cursor = cnxn.cursor()
sql = "SELECT * FROM TABLE"
df = psql.frame_query(sql, cnxn)
cnxn.close()
    
这似乎是最好的方法,因为你不需要手动使用.keys()来获取列的索引。 可能Daniel的答案是在这个方法存在之前写的。 你也可以使用pandas.io.sql.read_frame()
@openwonk 在上面的代码片段中,如何实现 pd.read_sql()
事实上,自从我上次回答后,我已经把 pyodbc pandas 放在一起使用了很多次。 加入新的答案和例子,仅供参考。
Nathan Gould
Nathan Gould
发布于 2021-02-13
0 人赞同

如果你使用SQLAlchemy的ORM而不是表达式语言,你可能会发现自己想把一个 sqlalchemy.orm.query.Query 类型的对象转换为一个Pandas数据框架。

最干净的方法是从查询的语句属性中获取生成的SQL,然后用pandas的 read_sql() 方法执行它。例如,从一个叫做 query 的查询对象开始。

df = pd.read_sql(query.statement, query.session.bind)
    
更有效的方法是,从sqlalchemy获取语句,让pandas自己用 pandas.read_sql_query 做查询,把 query.statement 传给它。请看这个答案。 stackoverflow.com/a/29528804/1273938
谢谢@LeoRochael!我编辑了我的答案。肯定是更干净了!
Paul H
Paul H
发布于 2021-02-13
0 人赞同

Edit 2014-09-30:

pandas现在有一个 read_sql 函数。你肯定想用它来代替。

Original answer:

在SQLAlchemy方面我无法帮助你 -- 我总是根据需要使用pyodbc、MySQLdb或psychopg2。但在这样做时,像下面这样简单的函数往往能满足我的需要。

import decimal
import pyodbc #just corrected a typo here
import numpy as np
import pandas
cnn, cur = myConnectToDBfunction()
cmd = "SELECT * FROM myTable"
cur.execute(cmd)
dataframe = __processCursor(cur, dataframe=True)
def __processCursor(cur, dataframe=False, index=None):
    Processes a database cursor with data on it into either
    a structured numpy array or a pandas dataframe.
    input:
    cur - a pyodbc cursor that has just received data
    dataframe - bool. if false, a numpy record array is returned
                if true, return a pandas dataframe
    index - list of column(s) to use as index in a pandas dataframe
    datatypes = []
    colinfo = cur.description
    for col in colinfo:
        if col[1] == unicode:
            datatypes.append((col[0], 'U%d' % col[3]))
        elif col[1] == str:
            datatypes.append((col[0], 'S%d' % col[3]))
        elif col[1] in [float, decimal.Decimal]:
            datatypes.append((col[0], 'f4'))
        elif col[1] == datetime.datetime:
            datatypes.append((col[0], 'O4'))
        elif col[1] == int:
            datatypes.append((col[0], 'i4'))
    data = []
    for row in cur:
        data.append(tuple(row))
    array = np.array(data, dtype=datatypes)
    if dataframe:
        output = pandas.DataFrame.from_records(array)
        if index is not None:
            output = output.set_index(index)
    else:
        output = array
    return output
    
我想你需要在上面的某个地方导入十进制?
@joefromct 也许吧,但这个答案太过时了,我真的应该把它全部删除,显示出pandas的方法。
这可能与某些人有关......我研究这个的原因是我的另一个问题,在这里使用read_sql()。 stackoverflow.com/questions/32847246/...
这与那些不能使用SQLAlchemy的人有关,因为它不支持所有数据库。
@lamecicle有点不同意。我记得, read_sql 仍然可以通过例如pyodbc、psychopg2等接受非SQLAlchemy连接。
Thomas Devoogdt
Thomas Devoogdt
发布于 2021-02-13
0 人赞同

MySQL Connector

对于那些使用mysql连接器的人,你可以使用这个代码作为开始。(感谢@Daniel Velkov)

Used refs:

  • Querying Data Using Connector/Python
  • Connecting to MYSQL with Python in 3 steps
  • # Setup MySQL connection db = mysql.connector.connect( host="<IP>", # your host, usually localhost user="<USER>", # your username password="<PASS>", # your password database="<DATABASE>" # name of the data base # You must create a Cursor object. It will let you execute all the queries you need cur = db.cursor() # Use all the SQL you like cur.execute("SELECT * FROM <TABLE>") # Put it all to a data frame sql_data = pd.DataFrame(cur.fetchall()) sql_data.columns = cur.column_names # Close the session db.close() # Show the data print(sql_data.head())
    Lintang Wisesa
    Lintang Wisesa
    发布于 2021-02-13
    0 人赞同

    1. Using MySQL-connector-python

    # pip install mysql-connector-python
    import mysql.connector
    import pandas as pd
    mydb = mysql.connector.connect(
        host = 'host',
        user = 'username',
        passwd = 'pass',
        database = 'db_name'
    query = 'select * from table_name'
    df = pd.read_sql(query, con = mydb)
    print(df)
    

    2. Using SQLAlchemy

    # pip install pymysql
    # pip install sqlalchemy
    import pandas as pd
    import sqlalchemy
    engine = sqlalchemy.create_engine('mysql+pymysql://username:password@localhost:3306/db_name')
    query = '''
    select * from table_name
    df = pd.read_sql_query(query, engine)
    print(df)
        
    简单而伟大的答案!
    Murali Bala
    Murali Bala
    发布于 2021-02-13
    0 人赞同

    Here's the code I use. Hope this helps.

    import pandas as pd
    from sqlalchemy import create_engine
    def getData():
      # Parameters
      ServerName = "my_server"
      Database = "my_db"
      UserPwd = "user:pwd"
      Driver = "driver=SQL Server Native Client 11.0"
      # Create the connection
      engine = create_engine('mssql+pyodbc://' + UserPwd + '@' + ServerName + '/' + Database + "?" + Driver)
      sql = "select * from mytable"
      df = pd.read_sql(sql, engine)
      return df
    df2 = getData()
    print(df2)
        
    DeshDeep Singh
    DeshDeep Singh
    发布于 2021-02-13
    0 人赞同

    这是对你的问题一个简短而干脆的回答。

    from __future__ import print_function
    import MySQLdb
    import numpy as np
    import pandas as pd
    import xlrd
    # Connecting to MySQL Database
    connection = MySQLdb.connect(
                 host="hostname",
                 port=0000,
                 user="userID",
                 passwd="password",
                 db="table_documents",
                 charset='utf8'
    print(connection)
    #getting data from database into a dataframe
    sql_for_df = 'select * from tabledata'
    df_from_database = pd.read_sql(sql_for_df , connection)
        
    Janak Mayer
    Janak Mayer
    发布于 2021-02-13
    0 人赞同

    像Nathan一样,我经常想把sqlalchemy或sqlsoup查询的结果转储到Pandas数据框中。 我自己对此的解决方案是

    query = session.query(tbl.Field1, tbl.Field2)
    DataFrame(query.all(), columns=[column['name'] for column in query.column_descriptions])
        
    如果你有一个查询对象。从sqlalchemy获取语句,让pandas自己用 pandas.read_sql_query 做查询,把 query.statement 传给它,这样更有效率。请看这个答案。 stackoverflow.com/a/29528804/1273938
    Wouter Overmeire
    Wouter Overmeire
    发布于 2021-02-13
    0 人赞同

    resoverall 是一个sqlchemy ResultProxy对象。你可以在 resoverall 中阅读更多关于它的信息。 sqlalchemy docs 后者解释了使用引擎和连接的基本用法。这里重要的是, resoverall 是像这样的口令。

    Pandas喜欢像对象一样的口令来创建它的数据结构,见 online docs

    祝你在sqlalchemy和pandas方面好运。

    openwonk
    openwonk
    发布于 2021-02-13
    0 人赞同

    只需同时使用 pandas pyodbc 。你必须根据你的数据库规格来修改你的连接字符串( connstr )。

    import pyodbc
    import pandas as pd
    # MSSQL Connection String Example
    connstr = "Server=myServerAddress;Database=myDB;User Id=myUsername;Password=myPass;"
    # Query Database and Create DataFrame Using Results
    df = pd.read_sql("select * from myTable", pyodbc.connect(connstr))
    

    我曾在多个企业数据库(如SQL Server、MySQL、MariaDB、IBM)中使用过pyodbc

    如何使用Pyodbc将这个数据框架再次写回MSSQL?除了使用sqlalchemy之外
    使用 to_sql 对象上的 DataFrame 方法。该方法默认为SQLite,所以你必须明确传递给它一个指向MSSQL数据库的对象。见 docs .
    我尝试了下面的方法,我有大约20万行,13列。15分钟后,它也没有完成。有什么想法吗? df.to_sql('tablename',engine,schema='schemaname',if_exists='append',index=False)
    这看起来确实很慢...我可能需要看到整个代码的运行情况,抱歉。我希望 pandas 能对轻型ETL工作进行更多优化,但可惜......
    BubbleGuppies
    BubbleGuppies
    发布于 2021-02-13
    0 人赞同

    这个问题是老问题了,但我想增加我的两点意见。我把这个问题理解为 "我想对我的[我的]SQL数据库运行一个查询,并把返回的数据存储为Pandas数据结构[DataFrame]"。

    从代码来看,你指的是mysql数据库,假设你是指pandas DataFrame。

    import MySQLdb as mdb
    import pandas.io.sql as sql
    from pandas import *
    conn = mdb.connect('<server>','<user>','<pass>','<db>');
    df = sql.read_frame('<query>', conn)
    
    conn = mdb.connect('localhost','myname','mypass','testdb');
    df = sql.read_frame('select * from testTable', conn)
    

    这将把testTable的所有行导入一个DataFrame。

    Antonio Fernandez
    Antonio Fernandez
    发布于 2021-02-13
    0 人赞同

    距离上一次发帖已经很久了,但也许对某人有帮助......。

    比Paul H.做空的方式。

    my_dic = session.query(query.all())
    my_df = pandas.DataFrame.from_dict(my_dic)
        
    kennyut
    kennyut
    发布于 2021-02-13
    0 人赞同

    这里是我的。如果你使用的是 "pymysql "的话,以备不时之需。

    import pymysql
    from pandas import DataFrame
    host   = 'localhost'
    port   = 3306
    user   = 'yourUserName'
    passwd = 'yourPassword'
    db     = 'yourDatabase'
    cnx    = pymysql.connect(host=host, port=port, user=user, passwd=passwd, db=db)
    cur    = cnx.cursor()
    query  = """ SELECT * FROM yourTable LIMIT 10"""
    cur.execute(query)
    field_names = [i[0] for i in cur.description]
    get_data = [xx for xx in cur]
    cur.close()
    cnx.close()
    df = DataFrame(get_data)
    df.columns = field_names
        
    江明哲
    江明哲
    发布于 2021-02-13
    0 人赞同

    pandas.io.sql.write_frame 已被废弃。 https://pandas.pydata.org/pandas-docs/version/0.15.2/generated/pandas.io.sql.write_frame.html

    应该改成使用pandas.DataFrame.to_sql https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.to_sql.html

    还有一个解决办法。 PYODBC to Pandas - DataFrame不工作 - 传递值的形状是(x,y), 指数意味着(w,z)

    从Pandas 0.12开始(我相信),你可以做到。

    import pandas
    import pyodbc
    sql = 'select * from table'
    cnn = pyodbc.connect(...)
    data = pandas.read_sql(sql, cnn)
    

    Prior to 0.12, you could do:

    import pandas
    from pandas.io.sql import read_frame
    import pyodbc
    sql = 'select * from table'
    cnn = pyodbc.connect(...)
    data = read_frame(sql, cnn)
        
    这是迄今为止最简单的方法
    Berto
    Berto
    发布于 2021-02-13
    0 人赞同

    我最好的方法是这样做

    db.execute(query) where db=db_class() #database class
        mydata=[x for x in db.fetchall()]
        df=pd.DataFrame(data=mydata)
        
    tanza9
    tanza9
    发布于 2021-02-13
    0 人赞同

    If the result type is ResultSet 你应该先把它转换为字典。然后将 数据框架列 将被自动收集。

    这在我的案例中是可行的。

    df = pd.DataFrame([dict(r) for r in resoverall])
        
    Raphvanns
    Raphvanns
    发布于 2021-02-13
    0 人赞同

    这里有一个我喜欢的简单解决方案。

    把你的数据库连接信息放在一个YAML文件中,放在一个安全的地方(不要把它放在代码版本中)。

    host: 'hostname' port: port_number_integer database: 'databasename' user: 'username' password: 'password'

    然后在一个字典中加载conf,打开db连接,在一个数据框中加载SQL查询的结果集。

    import yaml
    import pymysql
    import pandas as pd
    db_conf_path = '/path/to/db-conf.yaml'
    # Load DB conf
    with open(db_conf_path) as db_conf_file:
        db_conf = yaml.safe_load(db_conf_file)
    # Connect to the DB
    db_connection = pymysql.connect(**db_conf)
    # Load the data into a DF
    query = '''
    SELECT *
    FROM my_table