【问题标题】:Best approach to query SQL server for numpy查询 SQL Server 以获取 numpy 的最佳方法
【发布时间】:2013-05-01 09:27:36
【问题描述】:

在之前的程序中,我从 csv 文件中读取数据,如下所示:

AllData = np.genfromtxt(open("PSECSkew.csv", "rb"),
                        delimiter=',',
                        dtype=[('CalibrationDate', datetime),('Expiry', datetime), ('B0', float), ('B1', float), ('B2', float), ('ATMAdjustment', float)],
                        converters={0: ConvertToDate, 1: ConvertToDate})

我现在正在编写一个非常相似的程序,但这次我想获得一个与 AllData 非常相似的数据结构(除了这次浮点数都在一个 csv 字符串中),但来自 SQL Server 而不是 csv文件。最好的方法是什么?

pyodbc 看起来它涉及到大量使用游标,我不熟悉并希望避免。我只想运行查询并以上述结构(或 C# 中的 DataTable)获取数据。

【问题讨论】:

  • 您能更具体地说明您需要什么吗?您有两个主要选择:使用 pyodbc 或其他库查询数据库,获取结果集并将其转换为 Python 数据结构;或使用特定于数据库的工具(例如 bcp.exe)将数据导出到平面文件,然后在 Python 中读取文件。目前还不清楚为什么 pyodbc 不适合你,它很容易使用,如果你喜欢 ORM,你可以将它与 sqlalchemy 一起使用。
  • @Pondlife pyodbc 可能非常合适,您能否指出一个示例,说明如何使用它将查询中的数据获取到类似于 genfromtext 一次性创建的数据结构中而不是有一个光标并且必须逐个记录地导航它?我不想采用平面文件的方法。
  • 我对 numpy 一无所知,尽管我已经成功地将 pyodbc 和 sqlalchemy 与 SQL Server 一起使用。但是查询总是返回结果集(pyodbc 中的游标),因此如果您想将该结果集放在另一个数据结构中,那么您必须以某种方式对其进行转换。您可能想问一个关于如何实现 numpy.genfromcursor() 等价物的问题,也许有更多知识的人可以提供帮助。
  • @Pondlife 谢谢,您能否发布一个小示例,将一般结果集从 pyodbc 转换为任何东西,比如元组数组或其他东西?我敢肯定,我将能够使其适应 numpy 结构。谢谢
  • @Pondlife 实际上我认为这可能是我正在寻找的东西:stackoverflow.com/questions/7061824/… 会试一试

标签: sql-server-2008 python-2.7 numpy genfromtxt


【解决方案1】:

使用熊猫怎么样?例如:

import psycopg2
import pandas

try :
    con = psycopg2.connect(
    host = "host",
    database = "innovate",
    user = "username",
    password = "password")
except:
    print "Could not connect to database."

data = pandas.read_sql_query("SELECT * FROM table", con)

【讨论】:

    【解决方案2】:

    与此同时,还有更好的方法。查看turbodbc 包。要将您的结果集转换为 NumPy 数组的 OrderedDict,只需执行以下操作:

    import turbodbc
    connection = turbodbc.connect(dsn="My data source name")
    cursor = connection.cursor()
    cursor.execute("SELECT 42")
    results = cursor.fetchallnumpy()
    

    它也应该比 pyodbc 快得多(取决于您的数据库,因子 10 是绝对可能的)。

    【讨论】:

      【解决方案3】:

      最后我只是使用了 pyodbc 并遍历游标/结果集,通过大量的试验和错误将每个结果放入手动构造的结构化数组中。如果有更直接的方法,我会全力以赴!

      import numpy as np
      import pyodbc as SQL
      from datetime import datetime
      
      
      cxn = SQL.connect('Driver={SQL Server};Server=myServer; Database=myDB; UID=myUserName; PWD=myPassword')
      c = cxn.cursor()
      
      #Work out how many rows the query returns in order to initialise the structured array with the correct number of rows
      num_rows = c.execute('SELECT count(*) FROM PSECSkew').fetchone()[0]
      
      #Create the structured array
      AllData = np.zeros(num_rows, dtype=[('CalibrationDate', datetime),('Expiry', datetime), ('B0', float), ('B1', float), ('B2', float), ('ATMAdjustment', float)])
      
      ConvertToDate = lambda s:datetime.strptime(s,"%Y-%m-%d")
      
      #iterate using the cursor and fill the structred array.
      r = 0
      for row in c.execute('SELECT * FROM PSECSkew ORDER BY CalibrationDate, Expiry'):
          AllData[r] = (ConvertToDate(row[0]), ConvertToDate(row[1])) + row[2:] #Note if you don't need manipulate the data (i.e. to convert the dates in my case) then just tuple(row) would have sufficed
          r = r + 1
      

      【讨论】:

        【解决方案4】:

        这是一个基于您链接到的other question 的最小示例:

        import pyodbc
        import numpy
        
        conn = pyodbc.connect('DRIVER={SQL Server};SERVER=MyServer;Trusted_Connection=yes;')
        cur = conn.cursor()
        cur.execute('select object_id from sys.objects')
        results = cur.fetchall()
        results_as_list = [i[0] for i in results]
        array = numpy.fromiter(results_as_list, dtype=numpy.int32)
        print array
        

        【讨论】:

        • 如果我像这样定义results_as_list [item for sublist in results for item in sublist] (在此处形成:stackoverflow.com/questions/952914/…),那么我可以在调用np.reshape(array, [-1, 4]) 后使其适用于浮动列,谢谢!但是有没有办法处理日期列呢?我试过dtype=[date, date, float, float, float, float] 但没有运气:(
        • @Dan 我对 Numpy 的了解不够,无法直接回答,但 documentation 表示您可以从 YYYY-MM-DD 格式的日期初始化 Numpy datetime 类型,所以也许您可以在查询中尝试CONVERTing SQL Server datetime 值到该格式:select convert(char(10), DateTimeColumn, 21)
        • 感谢您的帮助,我无法使用此方法,因为我无法弄清楚如何让它接受多种数据类型,但我接受了您关于按顺序使用光标进行迭代的建议将其“转换”为我想要的数据结构并最终到达那里。解决方案提供。再次感谢!
        猜你喜欢
        • 2010-09-30
        • 2010-09-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-19
        相关资源
        最近更新 更多