You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python-Django Rest Framework单查询统计多表总行数问题

单查询统计多表行数(PostgreSQL + Django REST Framework)

无过滤条件的批量统计

如果所有表只需要统计总行数,可通过PostgreSQL的UNION ALL将多个COUNT(*)查询合并为单次请求,避免多次数据库往返:

from django.db import connection
from your_app.models import CommonModel

def get_table_row_counts():
    # 获取所有继承自CommonModel的子模型对应的数据库表名
    sub_models = CommonModel.__subclasses__()
    table_names = [model._meta.db_table for model in sub_models]
    
    # 构建每个表的统计子查询
    query_parts = []
    for table in table_names:
        query_parts.append(f"SELECT '{table}' AS table_name, COUNT(*) AS row_count FROM {table}")
    
    # 合并为单查询
    final_sql = " UNION ALL ".join(query_parts)
    
    # 执行并解析结果
    with connection.cursor() as cursor:
        cursor.execute(final_sql)
        results = cursor.fetchall()
    
    # 转换为要求的字典格式
    return {table: count for table, count in results}

带自定义过滤条件的批量统计

如果部分表需要添加过滤规则(比如某表只统计状态为激活的数据),只需给对应表的查询添加WHERE子句即可:

from django.db import connection
from your_app.models import CommonModel, Table1, Table2

def get_filtered_table_counts():
    # 定义各表的过滤条件,无过滤的表无需配置
    filter_rules = {
        Table1._meta.db_table: "WHERE status = 1",
        Table2._meta.db_table: "WHERE created_at >= CURRENT_DATE - INTERVAL '30 days'"
    }
    
    sub_models = CommonModel.__subclasses__()
    table_names = [model._meta.db_table for model in sub_models]
    
    query_parts = []
    for table in table_names:
        filter_clause = filter_rules.get(table, "")
        query_parts.append(f"SELECT '{table}' AS table_name, COUNT(*) AS row_count FROM {table} {filter_clause}")
    
    final_sql = " UNION ALL ".join(query_parts)
    
    with connection.cursor() as cursor:
        cursor.execute(final_sql)
        results = cursor.fetchall()
    
    return {table: count for table, count in results}

近似统计(高性能非精确场景)

如果对统计精度要求不高,可直接查询PostgreSQL的系统视图pg_stat_user_tables获取近似行数,无需全表扫描,性能大幅提升:

from django.db import connection
from your_app.models import CommonModel

def get_approx_table_counts():
    sub_models = CommonModel.__subclasses__()
    table_names = [model._meta.db_table for model in sub_models]
    table_name_list = ", ".join([f"'{t}'" for t in table_names])
    
    sql = f"""
        SELECT relname AS table_name, n_live_tup AS row_count
        FROM pg_stat_user_tables
        WHERE relname IN ({table_name_list})
    """
    
    with connection.cursor() as cursor:
        cursor.execute(sql)
        results = cursor.fetchall()
    
    return {table: count for table, count in results}

注意:n_live_tup来自PostgreSQL的统计信息,更新频率由autovacuum控制,可能存在一定延迟,适合后台统计、仪表盘等非实时精确场景。

集成到DRF视图

将上述函数集成到DRF的API视图中即可:

from rest_framework.views import APIView
from rest_framework.response import Response

class TableCountAPIView(APIView):
    def get(self, request):
        counts = get_table_row_counts()  # 或调用过滤版/近似版函数
        return Response(counts)

内容的提问来源于stack exchange,提问作者Tan Sang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 15:25:16