我有一个包含tablename,列列表的JSON有效负载--如何使用pypika从它构建一个SELECT查询?
到目前为止,我已经能够使用字符串列列表,但不能使用函数、分析等进行高级查询。
from pypika import Table, Query, functions as fn
def generate_sql (tablename, collist):
table = Table(tablename)
columns = [str(table)+'.'+each for each in collist]
q = Query.from_(table).select(*columns)
return q.get_sql(quote_char=None)
tablename = 'customers'
collist = ['id', 'fname', 'fn.Sum(revenue)']
print (generate_sql(tablename, collist)) #1
table = Table(tablename)
q = Query.from_(table).select(table.id, table.fname, fn.Sum(table.revenue))
print (q.get_sql(quote_char=None)) #2#1产出
SELECT "customers".id,"customers".fname,"customers".fn.Sum(revenue) FROM customers#2正确输出
SELECT id,fname,SUM(revenue) FROM customers发布于 2022-09-21 08:37:32
您不应该试图将查询单独组装到字符串中,这违背了pypika的全部目的。
在这种情况下,如果表的名称和列以文本形式出现在json对象中,您可以使用* to unpack --来自collist的值--并使用syntax obj[key]来获得带有字符串的table属性。
q = Query.from_(table).select(*(table[col] for col in collist))
# SELECT id,fname,fn.Sum(revenue) FROM customers嗯..。这对fn.Sum(revenue)不太适用。目标是获得SUM(revenue)。
从这个角度来看,这可能会变得更加复杂。如果您只发送您知道属于该表的列名,则上述解决方案就足够了。
但是,如果您有复杂的sql表达式,引用sql函数甚至不同的表,我建议您重新考虑将其作为json发送的决定。您可能会得到像pypika本身这样复杂的东西,比如自定义解析器或wathever。比这里更好的选择是更改json响应对象的格式。
如果您知道您只需要支持一组非常有限的功能,这可能是可行的。例如,您可以假定以下约束:
所有列名只引用一个表,没有联接或别名fn.
等花哨的东西作为前缀
然后你就可以做这样的事情:
from pypika import Table, Query, functions as fn
import re
tablename = 'customers'
collist = ['id', 'fname', 'fn.Sum(revenue / 2)', 'revenue % fn.Count(id)']
def parsed(cols):
pattern = r'(?:\bfn\.[a-zA-Z]\w*)|([a-zA-Z]\w*)'
subst = lambda m: f"{'' if m.group().startswith('fn.') else 'table.'}{m.group()}"
yield from (re.sub(pattern, subst, col) for col in cols)
table = Table(tablename)
env = dict(table=table, fn=fn)
q = Query.from_(table).select(*(eval(col, env) for col in parsed(collist)))
print (q.get_sql(quote_char=None)) #2输出:
SELECT id,fname,SUM(revenue/2),MOD(revenue,COUNT(id)) FROM customershttps://stackoverflow.com/questions/73779733
复制相似问题