我有两个相当简单的查询,在SQL
中看起来像这样SELECT COUNT(known), item FROM log GROUP BY item
SELECT COUNT(known), item FROM (SELECT known, item FROM log WHERE known == 1) GROUP BY item
对于具有“已知”,“项目”列的表“log”,两个查询都会对行进行计数,每个项目的行数是一个,另一个是每个项目的行数是多少将“已知”字段设置为1的表。这是我直接使用SQLite的程度,并且我还能够将其转换为SQLAlchemy表达式。
我想做一些可能有点复杂的事情。我想将两个查询的结果写入另一个表,可能会覆盖那里的条目。架构看起来有点像这样。
CREATE TABLE fractions (
id INTEGER NOT NULL,
item INTEGER,
sum_known_only FLOAT NOT NULL,
sum FLOAT NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY(item) REFERENCES items (id),
)
如何用sqlalchemy表达式语言表达这样一个复杂的表达式?
奖金将是:我可以使用子查询为每个sum
构建sum_known_only
和item
的分数吗?
我很欣赏SQLAlchemy表达式语言(不是ORM)和一般的SQL提示,两者对我都非常有帮助。
答案 0 :(得分:0)
请注意,我假设(因为该字段为FLOAT
)有一个Log.value
列,其中包含您实际汇总的值,而不仅仅是进行简单计数(这将是更简单)。
下面的查询应该允许您在一个查询中选择两个值,其余的答案将使用它:
one_select = (
session
.query(
Log.item.label("item"),
# func.count(Log.item).label("num_all"),
# func.sum(case([(Log.known == 1, 1)], 0)).label("num_known"),
func.sum(Log.value).label("sum_all"),
func.sum(case([(Log.known == 1, Log.value)], 0)).label("sum_known_only")
)
.group_by(Log.item)
)
插入新记录非常简单,但为了进行全面更新,我们还需要先删除现有记录,因此功能如下:
def delete_insert():
"""
First delete from Fraction table, then insert *all* values.
+ rather simple
- probably not the most efficient for the large table
"""
session.flush()
# 1. first delete existing ones
subq = exists(
select([1]).where(Log.item == Fraction.item).correlate(Fraction))
de_ = delete(Fraction).where(subq)
session.execute(de_)
# 2. now insert all
ins = (insert(Fraction).from_select(
(Fraction.item, Fraction.sum, Fraction.sum_known_only), one_select))
session.execute(ins)
session.commit()
还可以创建它的update_insert
版本,首先我们更新现有Fraction
记录的值,然后插入新记录。但是如果您指定数据库引擎以及构建分数的意思,那么更新会涉及更多,但也很乐意提供它。