如何用sqlalchemy编写自定义聚合函数?
我该如何使用SQLAlchemy编写自己的聚合函数呢?举个简单的例子,我想用numpy来计算方差。在sqlite中,它的写法是这样的:
import sqlite3 as sqlite
import numpy as np
class self_written_SQLvar(object):
def __init__(self):
import numpy as np
self.values = []
def step(self, value):
self.values.append(value)
def finalize(self):
return np.array(self.values).var()
cxn = sqlite.connect(':memory:')
cur = cxn.cursor()
cxn.create_aggregate("self_written_SQLvar", 1, self_written_SQLvar)
# Now - how to use it:
cur.execute("CREATE TABLE 'mytable' ('numbers' INTEGER)")
cur.execute("INSERT INTO 'mytable' VALUES (1)")
cur.execute("INSERT INTO 'mytable' VALUES (2)")
cur.execute("INSERT INTO 'mytable' VALUES (3)")
cur.execute("INSERT INTO 'mytable' VALUES (4)")
a = cur.execute("SELECT avg(numbers), self_written_SQLvar(numbers) FROM mytable")
print a.fetchall()
>>> [(2.5, 1.25)]
2 个回答
-1
首先,你需要从sqlalchemy导入func这个功能。
你可以这样写:
func.avg('字段名')
或者这样写:func.avg('字段名').label('用户定义的名称')
如果想了解更多信息,你可以查看这个链接:
http://www.sqlalchemy.org/docs/05/ormtutorial.html#using-subqueries
13
新聚合函数的创建依赖于后台的具体实现,必须直接通过底层连接的API来完成。SQLAlchemy并没有提供创建这些函数的功能。
不过,一旦创建好之后,你就可以在SQLAlchemy中正常使用它们。
举个例子:
import sqlalchemy
from sqlalchemy import Column, Table, create_engine, MetaData, Integer
from sqlalchemy import func, select
from sqlalchemy.pool import StaticPool
from random import randrange
import numpy
import sqlite3
class NumpyVarAggregate(object):
def __init__(self):
self.values = []
def step(self, value):
self.values.append(value)
def finalize(self):
return numpy.array(self.values).var()
def sqlite_memory_engine_creator():
con = sqlite3.connect(':memory:')
con.create_aggregate("np_var", 1, NumpyVarAggregate)
return con
e = create_engine('sqlite://', echo=True, poolclass=StaticPool,
creator=sqlite_memory_engine_creator)
m = MetaData(bind=e)
t = Table('mytable', m,
Column('id', Integer, primary_key=True),
Column('number', Integer)
)
m.create_all()
现在进行测试:
# insert 30 random-valued rows
t.insert().execute([{'number': randrange(100)} for x in xrange(30)])
for row in select([func.avg(t.c.number), func.np_var(t.c.number)]).execute():
print 'RESULT ROW: ', row
这会打印出(当SQLAlchemy的语句回显功能开启时):
2009-06-15 14:55:34,171 INFO sqlalchemy.engine.base.Engine.0x...d20c PRAGMA
table_info("mytable")
2009-06-15 14:55:34,174 INFO sqlalchemy.engine.base.Engine.0x...d20c ()
2009-06-15 14:55:34,175 INFO sqlalchemy.engine.base.Engine.0x...d20c
CREATE TABLE mytable (
id INTEGER NOT NULL,
number INTEGER,
PRIMARY KEY (id)
)
2009-06-15 14:55:34,175 INFO sqlalchemy.engine.base.Engine.0x...d20c ()
2009-06-15 14:55:34,176 INFO sqlalchemy.engine.base.Engine.0x...d20c COMMIT
2009-06-15 14:55:34,177 INFO sqlalchemy.engine.base.Engine.0x...d20c INSERT
INTO mytable (number) VALUES (?)
2009-06-15 14:55:34,177 INFO sqlalchemy.engine.base.Engine.0x...d20c [[98],
[94], [7], [1], [79], [77], [51], [28], [85], [26], [34], [68], [15], [43],
[52], [97], [64], [82], [11], [71], [27], [75], [60], [85], [42], [40],
[76], [12], [81], [69]]
2009-06-15 14:55:34,178 INFO sqlalchemy.engine.base.Engine.0x...d20c COMMIT
2009-06-15 14:55:34,180 INFO sqlalchemy.engine.base.Engine.0x...d20c SELECT
avg(mytable.number) AS avg_1, np_var(mytable.number) AS np_var_1 FROM mytable
2009-06-15 14:55:34,180 INFO sqlalchemy.engine.base.Engine.0x...d20c []
RESULT ROW: (55.0, 831.0)
注意,我没有使用SQLAlchemy的ORM(只用了SQLAlchemy的SQL表达部分),但你也可以使用ORM。