如果问题标题没有描述性/措辞不当,我们深表歉意。
我希望能够计算在满足特定条件的行中出现特定值的实例数。考虑以下两个表,queues
和 queue_contents
队列表:
+----+---------+
| id | name |
+----+---------+
| 1 | queue A |
| 2 | queue B |
| 3 | queue C |
+----+---------+
queue_contents 表:
+-----+----------+--------+
| id | queue_id | foo_id |
+-----+----------+--------+
| 1 | 1 | 10 |
| 2 | 1 | 11 |
| 3 | 1 | 12 |
| 5 | 2 | 20 |
| 6 | 2 | 21 |
| 7 | 2 | 23 |
| 8 | 2 | 24 |
| 9 | 3 | 10 |
| 10 | 3 | 11 |
| 11 | 3 | 20 |
| 12 | 3 | 30 |
+-----+----------+--------+
当我查询 queue_id == 3
+----------+------------+-------------+-----------------------+
| queue_id | queue_name | total_count | contained_in_this_one |
+----------+------------+-------------+-----------------------+
| 1 | queue A | 3 | 2 |
| 2 | queue B | 4 | 1 |
+----------+------------+-------------+-----------------------+
我不知道如何计算 queue_contents.foo_id WHERE queue_contents.queue_id == 3
中出现的 foo_id
的实例数
获取每个队列的 total_count
已经足够简单了,但是在设置子查询和条件时,我感到很困惑。我觉得解决方案涉及使用子查询并计算该子查询中出现的 foo_id
的数量,但我无法让它工作。我不会包括我尝试过的以下查询的 maaaany 迭代,尽管这会让您了解我所处的轨道:
foo_id
在此查询中
sq = db_session.query(Foo.id.label('foo_id')) \
.join(QueueContent, QueueContent.foo_id == Foo.id) \
.filter(QueueContent.queue_id == 3) \
.subquery('sq')
foo_alias = aliased(Foo)
q2 = db_session.query(func.count(Foo.id).label('total_in_task'),
func.count(foo_alias.id).label('count_in_this_task'),
Queue.id.label('queue_id'),
Queue.name.label('queue_name')) \
.join(foo_alias, foo_alias.id == Foo.id) \
.join(QueueContent, QueueContent.foo_id == Foo.id) \
.join(Queue, Queue.id == QueueContent.queue_id) \
.filter(Queue.id != 3) \
.group_by('queue_name', 'queue_id')
最佳答案
如果 queue_id
组不包含 foo_id
重复项,您可以使用 LEFT JOIN:
qc2 = aliased(QueueContent)
session.query(QueueContent.queue_id,
func.count(),
func.count(qc2.foo_id)).\
outerjoin(qc2, and_(qc2.queue_id == 3,
qc2.foo_id == QueueContent.foo_id)).\
filter(QueueContent.queue_id != 3).\
group_by(QueueContent.queue_id)
如果他们这样做,您可以使用包含在 NULLIF 中的 EXISTS 子查询表达式(或转换为整数并求和):
qc2 = aliased(QueueContent)
sq = session.query(qc2).\
filter_by(queue_id=3, foo_id=QueueContent.foo_id).\
exists()
session.query(QueueContent.queue_id,
func.count(),
func.count(func.nullif(sq, False))).\
filter(QueueContent.queue_id != 3).\
group_by(QueueContent.queue_id)
这两种变体都使用了 COUNT(expression) 生成 expression 的值不为 NULL 的行数这一事实。
关于python - 使用 SQLAlchemy 计算结果集中包含的值实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51527075/