2

我的数据库中有下表

  Name     |    total_stars   |      total_reviews
 Item A             27                       7
 Item B             36                       9
 Item C             27                       7
 Item D             30                       6
 Item E             0                        0
 Item F             0                        0
 Item F             15                       3

我正在看这篇文章,并试图在 postgresql 数据库中实现贝叶斯排名。

给出的排名公式是

br = ( (avg_num_votes * avg_rating) + (this_num_votes * this_rating) ) / 
(avg_num_votes + this_num_votes)

在哪里:

  • avg_num_votes:所有num_votes>0的项目的平均票数
  • avg_rating:每个项目的平均评分(同样,那些有 num_votes>0 的项目)
  • this_num_votes:该项目的投票数
  • this_rating:这个项目的评分

这是我提出的查询,但它不起作用:

with avg_num_votes as (
      select AVG(total_reviews) 
           from business 
           where total_reviews != 0), 
       avg_rating as (
          select AVG(total_stars/total_reviews) 
          from business 
          where total_reviews != 0)
select * from business 
  order by ((avg_num_votes * avg_rating) + (total_stars)) / (avg_num_votes + total_reviews);

我正进入(状态:ERROR: column "avg_num_votes" does not exist

4

2 回答 2

2

Postgres 中的运算符WITH仅用于创建要在主查询中使用的其他工作查询。

此查询在 FROM 子句中使用子选择,并按预期工作:

SELECT business.* FROM business,
     (SELECT avg(total_reviews) AS v
      FROM business 
      WHERE total_reviews != 0
     ) AS avg_num_votes,
     (SELECT avg(total_stars/total_reviews) AS v 
      FROM business 
      WHERE total_reviews != 0
     ) AS avg_rating
ORDER BY ((avg_num_votes.v * avg_rating.v) + (total_stars)) / (avg_num_votes.v + total_reviews)

编辑:实际上,使用WITH也是可能的,但与第一种形式相比似乎并不短。此外,它的可移植性较差 - 第一个解决方案将适用于 MySQL,但这不会:

WITH
    avg_num_votes AS (
        SELECT avg(total_reviews) AS v
        FROM business 
        WHERE total_reviews != 0
    ),
    avg_rating AS (
        SELECT avg(total_stars/total_reviews) AS v
        FROM business
        WHERE total_reviews != 0
    )
SELECT business.*
FROM business, avg_num_votes, avg_rating
ORDER BY ((avg_num_votes.v * avg_rating.v) + (total_stars)) / (avg_num_votes.v + total_reviews)
于 2012-12-20T06:17:15.590 回答
1

SQL小提琴

with av as (
    select avg(total_reviews) avg_num_votes
    from business
    where total_reviews > 0
), ar as (
    select name, avg(total_stars * 1.0 / total_reviews) avg_rating
    from business
    where total_reviews > 0
    group by name
)
select b.*, avg_rating, avg_num_votes,
    (avg_num_votes * avg_rating + total_stars)
    /
    (avg_num_votes + total_reviews) br
from
    business b
    left join
    ar on ar.name = b.name
    inner join
    av on true
order by br, b.name
    ;
  name  | total_stars | total_reviews |     avg_rating     |   avg_num_votes    |                 br                 
--------+-------------+---------------+--------------------+--------------------+------------------------------------
 Item A |          27 |             7 | 3.8571428571428571 | 6.4000000000000000 | 3.85714285714285712238805970149254
 Item C |          27 |             7 | 3.8571428571428571 | 6.4000000000000000 | 3.85714285714285712238805970149254
 Item B |          36 |             9 | 4.0000000000000000 | 6.4000000000000000 | 4.00000000000000000000000000000000
 Item D |          30 |             6 | 5.0000000000000000 | 6.4000000000000000 | 5.00000000000000000000000000000000
 Item F |           0 |             0 | 5.0000000000000000 | 6.4000000000000000 | 5.00000000000000000000000000000000
 Item F |          15 |             3 | 5.0000000000000000 | 6.4000000000000000 | 5.00000000000000000000000000000000
 Item E |           0 |             0 |                    | 6.4000000000000000 |                                   
于 2012-12-20T10:55:15.030 回答