首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用PyPika从API有效负载动态生成选择列表

如何使用PyPika从API有效负载动态生成选择列表
EN

Stack Overflow用户
提问于 2022-09-19 22:04:48
回答 1查看 44关注 0票数 0

我有一个包含tablename,列列表的JSON有效负载--如何使用pypika从它构建一个SELECT查询?

到目前为止,我已经能够使用字符串列列表,但不能使用函数、分析等进行高级查询。

代码语言:javascript
复制
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产出

代码语言:javascript
复制
SELECT "customers".id,"customers".fname,"customers".fn.Sum(revenue) FROM customers

#2正确输出

代码语言:javascript
复制
SELECT id,fname,SUM(revenue) FROM customers
EN

回答 1

Stack Overflow用户

发布于 2022-09-21 08:37:32

您不应该试图将查询单独组装到字符串中,这违背了pypika的全部目的。

在这种情况下,如果表的名称和列以文本形式出现在json对象中,您可以使用* to unpack --来自collist的值--并使用syntax obj[key]来获得带有字符串的table属性。

代码语言:javascript
复制
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.

  • no

  • --所有函数都将以窗口函数、distinct、count(*).

等花哨的东西作为前缀

然后你就可以做这样的事情:

代码语言:javascript
复制
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

输出:

代码语言:javascript
复制
SELECT id,fname,SUM(revenue/2),MOD(revenue,COUNT(id)) FROM customers
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73779733

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档