postgresql 使用repeat时,在select和error中添加变量

68de4m5k  于 2023-03-01  发布在  PostgreSQL
关注(0)|答案(3)|浏览(135)

假设如下,

create table person (id serial primary key);
create table person_rating (
  id serial primary key,
  person_id bigint references person,
  rating smallint constraint rating_person_rating_check check (rating > 0 and rating <= 5)
);

insert into person values (1);
insert into person_rating values
  (1, 1, 5),
  (2, 1, 2),
  (3, 1, 5),
  (4, 1, 1);

我正在尝试运行以下查询:

select
    round(avg(rating)::numeric(10, 2), 2) as rating_averaged,
    ceil(avg(rating)::numeric(10, 2)) as rating_rounded_up,
    concat(
      repeat('★', ceil(avg(rating)::numeric(10, 2))),
      repeat('☆', 5 - ceil(avg(rating)::numeric(10, 2)))
    ) as rating_as_stars
from person_rating;

我期待以下结果:

{
    "rating_averaged": 3.25,
    "rating_rounded_up": 4,
    "rating_as_stars": "★★★★☆"
}

我遇到以下错误:

Query Error: error: function repeat(unknown, numeric) does not exist

奇怪的是,基本的repeat选择工作,例如:

select repeat('hello! ', 2);

我也尝试过将其转换为::text::varchar,但错误仍然存在。
我担心的另一个问题是重复。例如,在这种情况下,下面的序列重复了4次:

avg(rating)::numeric(10, 2)

我该怎么解决这个问题?
Fiddle

q7solyqu

q7solyqu1#

还将repeat的第二个参数强制转换为integer

wz1wpwve

wz1wpwve2#

avg(any integer type)函数总是返回一个数值,因此重复转换其结果(::numeric(10,2))是不必要的。另外,由于其他人已经指出重复()函数要求第二个参数为整数,这需要强制转换。除此之外,rating的操作可以限制为CTE,减少repeat()函数的复杂性/冗长性。总的来说,查询减少为:(参见demo

with ratings(rating_averaged, rating_rounded_up) as 
     ( select round(avg(rating), 2) 
            , ceil(round(avg(rating),2))::integer  
         from person_rating
     )  --select * from ratings;
select rating_averaged 
     , rating_rounded_up 
     , concat( repeat('★', rating_rounded_up )
             , repeat('☆', 5 - rating_rounded_up)
             ) as rating_as_stars 
from ratings;
baubqpgj

baubqpgj3#

第二个参数必须为整数:

select
    round(avg(rating)::numeric(10, 2), 2) as rating_averaged,
    ceil(avg(rating)::numeric(10, 2)) as rating_rounded_up,
    concat(
      repeat('★', ceil(avg(rating)::numeric(10, 2))::integer),
      repeat('☆', 5 - ceil(avg(rating)::numeric(10, 2))::integer)
    ) as rating_as_stars
from person_rating;

此外,如果您希望保持代码简洁,我建议创建一个函数,该函数基于“rating”参数返回一个评级。

相关问题