以更简单的方式编写查询以实现 pymysql 更好的替换

问题描述 投票:0回答:1

我有以下查询,我想在其中替换列表中的级别和内容的值。

SELECT count(DISTINCT(USERS)) AS TOTAL_USERS FROM db.CCN 
JOIN UCR ON CCN.COLLECTIVE = UCR.COLLECTIVE 
WHERE USER NOT LIKE 'IMM%%' 
AND USER NOT LIKE 'UWEB%%'
AND( 
    (CCN.CONTENT='C1' AND CCN.LEVEL='L1')OR
    (CCN.CONTENT='C2' AND CCN.LEVEL='L2')OR
    (CCN.CONTENT='C3' AND CCN.LEVEL='L3')
)

有什么方法可以简化此查询,以便能够使用 python 替换内容和级别的值?我曾想过使用两个 IN 表达式,但这不会以相同的方式工作。我有必须替换的内容和级别的组合列表。我宁愿避免当前的语法,因为我认为我必须使用 f 字符串来构建查询,并且我更喜欢使用 pymysql 支持的正确替换。我尝试过在 WHERE 中使用 CONCAT,但这太慢了。

谢谢你,

python mariadb pymysql
1个回答
0
投票

动态生成

OR
表达式序列,以创建具有适当数量的
%s
占位符的参数化语句。

content_levels = [('C1', 'L1'), ('C2', 'L2'), ('C3', 'L3')]
conditions = ' OR '.join(['(CCN.CONTENT=%s AND CCN.LEVEL=%s)'] * len(content_levels))
sql = f'''SELECT count(DISTINCT(USERS)) AS TOTAL_USERS FROM db.CCN 
JOIN UCR ON CCN.COLLECTIVE = UCR.COLLECTIVE 
WHERE USER NOT LIKE 'IMM%%' 
AND USER NOT LIKE 'UWEB%%'
AND ({conditions})'''
# flatten content_levels
params = sum(content_levels, start=())
cursor.execute(sql, params)
© www.soinside.com 2019 - 2024. All rights reserved.