ดำเนินการไฟล์ SQL ส่งกลับผลลัพธ์เป็น Pandas DataFrame

ฉันมีแบบสอบถาม SQL Server ที่ซับซ้อนที่ฉันต้องการดำเนินการจาก Python และส่งคืนผลลัพธ์เป็น Pandas DataFrame

ฐานข้อมูลของฉันเป็นแบบอ่านอย่างเดียว ดังนั้นฉันจึงไม่มีตัวเลือกมากมายเหมือนกับคำตอบอื่นๆ ที่ใช้สำหรับการสืบค้นที่ซับซ้อนน้อยกว่า

คำตอบนี้มีประโยชน์ แต่ฉันยังคงได้รับ TypeError: 'NoneType' object is not iterable ต่อไป

ตัวอย่าง SQL

นี่ไม่ใช่แบบสอบถามจริง - เพียงเพื่อแสดงให้เห็นว่าฉันมีตารางชั่วคราว การใช้ตารางชั่วคราวทั่วโลกเนื่องจากการสืบค้นของฉันล้มเหลวก่อนหน้านี้โดยใช้ตารางชั่วคราวในเครื่อง: ดูคำถามนี้

SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

IF OBJECT_ID('tempdb..##temptable') IS NOT NULL DROP TABLE ##temptable
IF OBJECT_ID('tempdb..##results') IS NOT NULL DROP TABLE ##results

DECLARE @closing_period int = 0, @starting_period int = 0

Select col1, col2, col3 into ##temptable from readonlytables

Select * into ##results from ##temptable

Select * from ##results

ดำเนินการค้นหาด้วย pyodbc และ pandas

conn = pyodbc.connect('db connection details')

sql = open('myquery.sql', 'r')
df = read_sql_query(sql.read(), conn)
sql.close()
conn.close()

ผลลัพธ์ - การติดตามสแต็กเต็ม

ypeError                                 Traceback (most recent call last)
<ipython-input-38-4fcfe4123667> in <module>
      5 
      6 sql = open('sql/month_end_close_hp.sql', 'r')
----> 7 df = pd.read_sql_query(sql.read(), conn)
      8 #sql.close()
      9 

C:\ProgramData\Anaconda3\lib\site-packages\pandas\io\sql.py in read_sql_query(sql, con, index_col, coerce_float, params, parse_dates, chunksize)
    330         coerce_float=coerce_float,
    331         parse_dates=parse_dates,
--> 332         chunksize=chunksize,
    333     )
    334 

C:\ProgramData\Anaconda3\lib\site-packages\pandas\io\sql.py in read_query(self, sql, index_col, coerce_float, params, parse_dates, chunksize)
   1632         args = _convert_params(sql, params)
   1633         cursor = self.execute(*args)
-> 1634         columns = [col_desc[0] for col_desc in cursor.description]
   1635 
   1636         if chunksize is not None:

TypeError: 'NoneType' object is not iterable

เมื่อฉันเรียกใช้แบบสอบถามในฐานข้อมูลของฉัน ฉันได้รับผลลัพธ์ที่คาดหวัง หากฉันส่งข้อความค้นหาเป็นสตริง ฉันจะได้รับผลลัพธ์ที่คาดหวังด้วย:

แบบสอบถามเป็นสตริง

conn = pyodbc.connect('db connection details')

sql = '''
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
SET NOCOUNT ON
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

IF OBJECT_ID('tempdb..##temptable') IS NOT NULL DROP TABLE ##temptable
IF OBJECT_ID('tempdb..##results') IS NOT NULL DROP TABLE ##results

DECLARE @closing_period int = 0, @starting_period int = 0

Select col1, col2, col3 into ##temptable from readonlytables

Select * into ##results from ##temptable

Select * from ##results
'''

df = read_sql(sql, conn)

conn.close()

ฉันคิดว่าอาจมีบางอย่างเกี่ยวข้องกับเครื่องหมายคำพูดเดี่ยวในข้อความค้นหาของฉัน


person terrah27    schedule 18.08.2020    source แหล่งที่มา
comment
สิ่งที่น่าสนใจคือ Select * into ##results from ##temptable จะต้องทำอะไรให้สำเร็จ นอกเหนือจากการทำซ้ำข้อมูล เหตุใดจึงต้องมีตารางชั่วคราวทั่วโลก   -  person Larnu    schedule 18.08.2020
comment
คุณสามารถโพสต์การติดตามสแต็กแบบเต็มได้ไหม   -  person Umar.H    schedule 18.08.2020
comment
หลังจาก sql = open('myquery.sql', 'r') ให้ลอง df = read_sql_query(sql.read(), conn)   -  person Gord Thompson    schedule 18.08.2020
comment
@Larnu - ฉันกำลังพยายามยกตัวอย่างสิ่งที่อยู่ในข้อความค้นหาของฉันโดยไม่ต้องโพสต์ข้อความค้นหาจริงๆ ตารางชั่วคราวในเครื่องไม่ทำงานเมื่อฉันส่งข้อความค้นหาเป็นสตริงดังนั้นฉันจึงเปลี่ยนเป็นโกลบอล (ตามคำตอบนี้)[stackoverflow.com/questions/37863125/   -  person terrah27    schedule 18.08.2020
comment
@Manakin เพิ่มการติดตามสแต็กแบบเต็ม   -  person terrah27    schedule 18.08.2020
comment
@GordThompson ขอบคุณสำหรับการจับสิ่งนี้ - ฉันมีรหัสของฉัน แต่ละเว้นในคำถาม น่าเสียดายที่นี่ไม่สามารถแก้ปัญหาได้   -  person terrah27    schedule 18.08.2020
comment
บรรทัดที่ 7 ในการติดตามสแต็กของคุณไม่ตรงกับโค้ดตัวอย่างของคุณ read() ยังคงหายไป   -  person Gord Thompson    schedule 18.08.2020
comment
ฉันไม่สามารถจำลองปัญหาของคุณได้ โค้ดนี้ใช้ได้ดีสำหรับฉัน   -  person Gord Thompson    schedule 19.08.2020


คำตอบ (1)


ฉันทำให้มันทำงานได้

ฉันต้องใช้ตัวแปรโกลบอลโดยแทนที่ @ ด้วย @@ ฉันสามารถทำให้แบบสอบถามทำงานได้ตามที่คาดไว้

DECLARE @@closing_period int = 0, @@starting_period int = 0

อัปเดต: ไดรเวอร์ ODBC ของฉันล้าสมัยมาก - หลังจากอัปเดตเป็นเวอร์ชันล่าสุด ฉันไม่ต้องการตารางชั่วคราวหรือตัวแปรส่วนกลางอีกต่อไป - และการสืบค้นทำงานเร็วขึ้นอย่างมาก

person terrah27    schedule 21.08.2020