简体   繁体   English

pd.read_sql - 不支持的格式字符错误 (0x27)

[英]pd.read_sql - Unsupported format character error (0x27)

As above, I'm trying to use pd.read_sql to query our mysql database, and getting an error for double/single quotes.如上所述,我正在尝试使用 pd.read_sql 查询我们的 mysql 数据库,并收到双引号/单引号错误。

When I remove the % operators from the LIKE clause (lines 84-87) the query runs, but these are needed.当我从 LIKE 子句(第 84-87 行)中删除 % 运算符时,查询运行,但这些是必需的。 I know I need to format the strings but I don't know how within such a big query.我知道我需要格式化字符串,但我不知道如何在这么大的查询中。

Here's the query:这是查询:

SELECT
    s.offer_id,
    s.cap_id,
    vi.make,
    vi.model,
    vi.derivative,
    i.vehicle_orders,
    s.lowest_offer,
    CASE
        WHEN f.previous_avg = f.previous_low THEN "n/a"
        ELSE FORMAT(f.previous_avg, 2)
    END as previous_avg,
    f.previous_low,
    CASE
        WHEN ( ( (s.lowest_offer - f.previous_avg) / f.previous_avg) * 100) = ( ( (s.lowest_offer - f.previous_low) / f.previous_low) * 100) THEN "n/a"
        ELSE CONCAT(FORMAT( ( ( (s.lowest_offer - f.previous_avg) / f.previous_avg) * 100), 2), "%")
    END as diff_avg,
    CONCAT(FORMAT( ( ( (s.lowest_offer - f.previous_low) / f.previous_low) * 100), 2), "%") as diff_low,
    s.broker,
    CASE
        WHEN s.in_stock = '1' THEN "In Stock"
        ELSE "Factory Order"
    END as in_stock,
    CASE
        WHEN s.special IS NOT NULL THEN "Already in Specials"
        ELSE "n/a"
    END as special
FROM

    (   SELECT o.id as offer_id,
               o.cap_id as cap_id,
               MIN(o.monthly_payment) as lowest_offer,
               b.name as broker,
               o.stock as in_stock,
               so.id as special
            FROM
                offers o
                INNER JOIN brands b ON ( o.brand_id = b.id )
                LEFT JOIN special_offers so ON ( so.cap_id = o.cap_id )
            WHERE
                ( o.date_modified >= DATE_ADD(NOW(), INTERVAL -1 DAY) OR o.date_created >= DATE_ADD(NOW(), INTERVAL -1 DAY) )
                AND o.deposit_value = 9
                AND o.term = 48
                AND o.annual_mileage = 8000
                AND o.finance_type = 'P'
                AND o.monthly_payment > 100
            GROUP BY 
                o.cap_id
            ORDER BY
                special DESC) s
                
INNER JOIN      
        
    (   SELECT o.cap_id as cap_id,
               AVG(o.monthly_payment) as previous_avg,
               MIN(o.monthly_payment) as previous_low
            FROM
                offers o
            WHERE
                o.date_modified < DATE_ADD(NOW(), INTERVAL -1 DAY)
                AND o.date_modified >= DATE_ADD(NOW(), INTERVAL -1 WEEK)
                AND o.deposit_value = 9
                AND o.term = 48
                AND o.annual_mileage = 8000
                AND o.finance_type = 'P'
                AND o.monthly_payment > 100
            GROUP BY
                o.cap_id ) f ON ( s.cap_id = f.cap_id )
                
LEFT JOIN

    (   SELECT a.cap_id as cap_id,
               v.manufacturer as make,
               v.model as model,
               v.derivative as derivative,
               COUNT(*) as vehicle_orders
            FROM
                    (    SELECT o.id,
                                o.name as name,
                                o.email as email,
                                o.date_created as date,
                                SUBSTRING_INDEX(SUBSTRING(offer_serialized, LOCATE("capId", offer_serialized) +12, 10), '"', 1) as cap_id
                            FROM moneyshake.orders o
                            WHERE o.name NOT LIKE 'test%'
                                  AND o.email NOT LIKE 'jawor%'
                                  AND o.email NOT LIKE 'test%'
                                  AND o.email NOT LIKE '%moneyshake%'
                                  AND o.phone IS NOT NULL
                                  AND o.date_created > DATE_ADD(NOW(), INTERVAL -1 MONTH)
                    ) a JOIN moneyshake.vehicles_view v ON a.cap_id = v.id
            GROUP BY
                v.manufacturer,
                v.model,
                v.derivative,
                a.cap_id) i ON ( f.cap_id = i.cap_id )
                
INNER JOIN
            
    (   SELECT v.id as id,
               v.manufacturer as make,
               v.model as model,
               v.derivative as derivative
            FROM moneyshake.vehicles_view v
            GROUP BY v.id ) vi ON s.cap_id = vi.id

WHERE
    ( ( s.lowest_offer - f.previous_low ) / f.previous_low) * 100 <= -15
GROUP BY
    s.cap_id

Thanks!谢谢!

That error occurs then the DBAPI layer (eg, mysqlclient) natively uses the "format" paramstyle and the percent sign ( % ) is misinterpreted as a format character instead of a LIKE wildcard.然后发生该错误,DBAPI 层(例如,mysqlclient)本机使用“格式”参数样式,并且百分号( % )被误解为格式字符而不是LIKE通配符。

The fix is to wrap the SQL statement in a SQLAlchemy text() object.修复方法是将 SQL 语句包装在 SQLAlchemy text() object 中。 For example, this will fail:例如,这将失败:

import pandas as pd
import sqlalchemy as sa

engine = sa.create_engine("mysql+mysqldb://scott:tiger@localhost:3307/mydb")

sql = """\
SELECT * FROM million_rows
WHERE varchar_col LIKE 'record00000%'
ORDER BY id
"""
df = pd.read_sql_query(sql, engine)

but simply changing the read_sql_query() call to但只需将read_sql_query()调用更改为

df = pd.read_sql_query(sa.text(sql), engine)

will work.将工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM