PostgreSQL查询优化:将统计总数total移至结果外层
Solution for Restructuring JSON Output in PostgreSQL
Got it, let's adjust your query to get the exact output structure you're after. The core issue here is separating the total count from individual paginated records instead of embedding it in every row. Here's how to fix it:
Direct Query Solution
SELECT json_build_object( 'total', (SELECT COUNT(*) FROM notifications WHERE title ILIKE '%a%'), 'data', array_to_json(array_agg(row_to_json(t))) ) FROM ( SELECT id, title FROM notifications WHERE title ILIKE '%a%' LIMIT 5 OFFSET 1 ) t;
Breakdown of how this works:
- The subquery for the
totalkey calculates the full count of matching records (ignoringLIMIT/OFFSET), so you get the real total number of entries matching your filter. - The main subquery
tfetches only the paginatedidandtitlefields you need, without the total cluttering each row. array_agg(row_to_json(t))converts the paginated rows into a clean JSON array, which we assign to thedatakey.json_build_objectwraps everything into your desired outer structure, withtotalat the top level anddataholding the list of records.
Efficient CTE Version (Reusing Filter Logic)
If you want to avoid running the WHERE clause twice (better for performance with large datasets), use a Common Table Expression (CTE) to reuse the filtered dataset:
WITH filtered_notifications AS ( SELECT id, title FROM notifications WHERE title ILIKE '%a%' ) SELECT json_build_object( 'total', (SELECT COUNT(*) FROM filtered_notifications), 'data', array_to_json(array_agg(row_to_json(t))) ) FROM ( SELECT id, title FROM filtered_notifications LIMIT 5 OFFSET 1 ) t;
This will output exactly the format you want:
{ "total":16, "data":[ { "title": "Sartaj ", "id": 3 }] }
内容的提问来源于stack exchange,提问作者Dinesh Jain
相关产品推荐
相关产品推荐

