我有一个与所需行匹配的数据库查询。假设(为简单起见):
select * from stats where id in (1, 2);
现在,我想为这些匹配行中的提取多个列的多个频率统计信息(不同值的数量):
-- `stats.status` is one such column
select status, count(*) from stats where id in (1, 2) group by 1 order by 2 desc;
-- `stats.category` is another column
select category, count(*) from stats where id in (1, 2) group by 1 order by 2 desc;
-- etc.
是否可以在SqlAlchemy中重用相同的基础查询?原始SQL也可以。
甚至更好的是,在一个命令中一次返回所有直方图?
我对性能最感兴趣,因为我不希望Postgres多次运行相同的行匹配,每一列一次又一次。唯一的变化是哪一列用于直方图分组。否则,它是同一组行。
答案 0 :(得分:3)
我不希望Postgres多次运行相同的行匹配
这是GROUPING SETS功能背后的动机之一。试试这个模型:
SELECT category, status, count(*)
FROM stats where id in (1,2)
GROUP BY grouping sets ((category),(status));
答案 1 :(得分:2)
用户Abelisto的注释和其他答案都具有在1个单个查询中为多个字段生成直方图所需的正确sql。
我对他们的工作唯一建议的建议是添加一个ORDER BY
子句,从OP的尝试看来,似乎需要在结果的顶部使用更频繁的标签。您可能会发现,使用python(而不是数据库)对结果进行排序更为简单。在这种情况下,请忽略order by子句带来的复杂性。
因此,修改后的查询将是:
SELECT category, status, count(*)
FROM stats
WHERE id IN (1, 2)
GROUP BY GROUPING SETS (
(category), (status)
)
ORDER BY
GROUPING(category, status), 3 DESC
也可以使用sqlalchemy表达相同的查询。
from sqlalchemy import *
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Stats(Base):
__tablename__ = 'stats'
id = Column(Integer, primary_key=True)
category = Column(Text)
status = Column(Text)
stmt = select(
[Stats.category, Stats.status, func.count(1)]
).where(
Stats.id.in_([1, 2])
).group_by(
func.grouping_sets(tuple_(Stats.category),
tuple_(Stats.status))
).order_by(
func.grouping(Stats.category, Stats.status),
func.count(1).desc()
)
调查输出,我们看到它生成了所需的查询(为清晰起见,在输出中添加了额外的换行符)
print(stmt.compile(compile_kwargs={'literal_binds': True}))
# outputs:
SELECT stats.category, stats.status, count(1) AS count_1
FROM stats
WHERE stats.id IN (1, 2)
GROUP BY GROUPING SETS((stats.category), (stats.status))
ORDER BY grouping(stats.category, stats.status), count(1) DESC