跨多个分组重用相同的查询?

Reuse same query across multiple group-bys?

我有一个与所需行匹配的数据库查询。让我们说(为简单起见):

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 也可以。

或者更好的是,return 所有直方图都在一个命令中?

我最感兴趣的是性能,因为我不希望 Postgres 多次 运行 同一行匹配,每列一次,一遍又一遍。唯一的变化是哪个列用于直方图分组。否则它是同一组行。

I don't want Postgres to run the same row-matching many times

这是 GROUPING SETS 功能背后的动机之一。试试这个模型:

SELECT category, status, count(*)
FROM stats where id in (1,2)
GROUP BY grouping sets ((category),(status));

用户 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