【问题标题】:Is there a way to return a total count and rows in a single psql query?有没有办法在单个 psql 查询中返回总计数和行数?
【发布时间】:2022-01-21 04:16:59
【问题描述】:

考虑以下几点:

CREATE TABLE IF NOT EXISTS person (
    id                  BIGSERIAL,
    favorite_color      TEXT,
    PRIMARY KEY (id)
);


INSERT INTO person (favorite_color) VALUES ('red');
INSERT INTO person (favorite_color) VALUES ('green');
INSERT INTO person (favorite_color) VALUES ('blue');
INSERT INTO person (favorite_color) VALUES ('blue');
INSERT INTO person (favorite_color) VALUES ('blue');

我现在想查询表,为favorite_color = blue 并返回所有行的所有行提供COUNT。如何使用单个 postgresql 查询实现以下输出?

{
    "total" 3,
    "results": [
        {"id": 3, "favorite_color": "blue"},
        {"id": 4, "favorite_color": "blue"},
        {"id": 5, "favorite_color": "blue"},
    ]
}

我知道怎么写SQL语句,我问是否可以写一个SQL语句来达到我想要的结果,反对两次访问数据库(一次用于计数,第二次用于结果)。

【问题讨论】:

  • 所以不是“反对两次打击数据库”,而是只打击一次,但更难? ??????

标签: sql json postgresql


【解决方案1】:

您可以使用count() 的窗口版本来获取计数。

SELECT json_build_object('total', max(total),
                         'results', json_agg(element))
       FROM (SELECT count(*) OVER () AS total,
                    row_to_json(person) AS element
                    FROM person
                    WHERE favorite_color = 'blue') AS x;

db<>fiddle

【讨论】:

  • 这里为什么需要使用max()
  • @KeSi-Kung:因为json_agg() 的聚合暗示。由于total 对每一行都是相同的,因此也可以使用min() 或其他可能的聚合函数。
【解决方案2】:

这是一个带有标量子查询且没有窗口函数或min() 的替代方案。让优化器独自完成它的工作。

with p as (select * from person where favorite_color = 'blue')
select jsonb_build_object(
 'total', count(*), 
 'results',  
 (
  select jsonb_agg(to_jsonb(t)) 
    from (select id, favorite_color from p) t
 ))
from p;

【讨论】:

  • 这似乎是返回表中所有行的计数,而不是与查询匹配的行。
  • @KeSi-Kung 哦,当然。答案已更新。
猜你喜欢
  • 2019-03-09
  • 2020-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-11
  • 2022-01-17
  • 2015-07-19
  • 1970-01-01
相关资源
最近更新 更多