【问题标题】:Correct way to fill a list from a SQL query using pyodbc使用 pyodbc 从 SQL 查询中填充列表的正确方法
【发布时间】:2014-02-05 13:03:43
【问题描述】:

这是从 Python 2.7 中的 SQL 查询中获取列表的正确方法吗?使用循环似乎有点虚假。有没有更简洁更好的方法?

import numpy as np
import pyodbc as SQL
from datetime import datetime

con = SQL.connect('Driver={SQL Server};Server=MyServer; Database=MyDB; UID=MyUser; PWD=MyPassword')
cursor = con.cursor()

#Function to convert the unicode dates returned by SQL Server into Python datetime objects
ConvertToDate = lambda s:datetime.strptime(s,"%Y-%m-%d")

#Parameters
Code = 'GBPZAR'

date_query = '''
             SELECT DISTINCT TradeDate 
             FROM MTM 
             WHERE Code = ? 
               and TradeDate > '2009-04-08' 
             ORDER BY TradeDate
            '''

#Get a list of dates from SQL
cursor.execute(date_query, [Code])
rows = cursor.fetchall()
Dates = [None]*len(rows) #Initialize array
r = 0
for row in rows:
    Dates[r] = ConvertToDate(row[0])
    r += 1

编辑:

当我想将查询放入结构化数组时怎么办?目前我做这样的事情:

#Initialize the structured array
AllData = np.zeros(num_rows, dtype=[('TradeDate', datetime),
                                    ('Expiry', datetime), 
                                    ('Moneyness', float),
                                    ('Volatility', float)])

#Iterate through the record set using the cursor and populate the structure array
r = 0
for row in cursor.execute(single_date_and_expiry_query, [TradeDate, Code, Expiry]):
    AllData[r] = (ConvertToDate(row[0]), ConvertToDate(row[1])) + row[2:] #Convert th0e date columns and concatenate the numeric columns
    r += 1

【问题讨论】:

    标签: python python-2.7 numpy pyodbc


    【解决方案1】:

    无需预先创建列表,您可以使用list.append() 代替。这也避免了必须保留一个计数器来索引到Dates

    我会在这里使用列表推导,在光标上循环直接以获取行:

    cursor.execute(date_query, [Code])
    Dates = [datetime.strptime(r[0], "%Y-%m-%d") for r in cursor]
    

    您可能希望将.date() 添加到datetime.strptime() 结果中以获取datetime.date 对象。

    遍历游标更可取,因为它避免将所有行作为列表加载到内存中,只是用另一个处理过的日期列表替换该列表。见cursor.fetchall() documentation

    由于这会将所有行读取到内存中,因此如果有很多行,则不应使用它。请考虑对行进行迭代。

    要生成您的 numpy.array,请不要预先填充。而是使用 numpy.asarray() 在生成器的帮助下将光标项转换为数组:

    dtype=[('TradeDate', datetime), ('Expiry', datetime), 
           ('Moneyness', float), ('Volatility', float)]
    dt = lambda v: datetime.strptime(v, "%Y-%m-%d")
    filtered_rows = ((dt(r[0]), dt(r[1]) + r[2:]) for r in cursor)
    all_values = np.asarray(filtered_rows, dtype=dtype)
    

    为了将来参考,您可以使用enumerate() 生成一个带有循环的计数器:

    for r, row in enumerate(rows):
        # r starts at 0 and counts along
    

    【讨论】:

    • 太好了,谢谢。如果我在那之后执行第二个查询,光标会重置吗?
    • 是的,每个新的.execute()都会重置光标。
    • 抱歉,刚刚添加到问题中。请看我的编辑。我可以使用这样的列表理解来获取结构化数组而不是列表吗?
    • enumerate() 的想法看起来很酷,这就像在 for-each 循环中获得自动计数器一样吗?
    • 是的,enumerate() 提供自动计数器。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-19
    • 2014-05-11
    • 1970-01-01
    相关资源
    最近更新 更多