在 postgresql 中,如何使用 window 函数而不是使用 count( ) 函数进行计数

In postgresql, how do you count using window functions instead of using count( ) function

我正在尝试查询电影列表,将它们分类以及每部电影的租借次数。我想使用 window 函数 来计算每部电影被租出的次数,同时被分组到每个类别并保留它们的行。

SELECT film_title, category_name, 
       COUNT (*) AS count_of_rentals
FROM 
       (SELECT f.film_id AS film_id,
              f.title AS film_title,
              c.name AS category_name,
              r.customer_id AS customer_id,
              rental_date AS rental_date
        FROM film f
        JOIN film_category fc
        ON f.film_id = fc.film_id
        JOIN category c
        ON c.category_id = fc.category_id 
        JOIN inventory i
        ON i.film_id = f.film_id
        JOIN rental r
        ON r.inventory_id = i.inventory_id
        WHERE c.name IN ('Animation', 'Children', 'Classics', 'Comedy', 'Family', 'Music')
        ORDER BY 3, 2) t1
GROUP BY 1, 2
ORDER BY 2, 1;

我能够使用 count 函数 获得我想要的结果,但我想使用 window 函数进行聚合。我该怎么做?提前谢谢你。

您可以修改并尝试如下相同的查询:

SELECT film_title, 
       category_name, 
       count_of_rentals
FROM (
        SELECT f.film_id AS film_id,
              f.title AS film_title,
              c.name AS category_name,
              r.customer_id AS customer_id,
              rental_date AS rental_date,
              count(*) over (partition by <column> order by <column>) count_of_rentals
              .
              .

IN (partition by <column> order by <column>) 您可以保留原始查询中的相同列

您不需要任何外部查询,而是需要在 count(*) window 函数的 partition by 子句中提及按列分组。

        SELECT f.film_id AS film_id,
              f.title AS film_title,
              c.name AS category_name,
              count(*) over (partition by f.title, c.name) count_of_rentals,
              r.customer_id AS customer_id,
              rental_date AS rental_date
        FROM film f
        JOIN film_category fc
        ON f.film_id = fc.film_id
        JOIN category c
        ON c.category_id = fc.category_id 
        JOIN inventory i
        ON i.film_id = f.film_id
        JOIN rental r
        ON r.inventory_id = i.inventory_id
        WHERE c.name IN ('Animation', 'Children', 'Classics', 'Comedy', 'Family', 'Music')
        ORDER BY 3, 2

您的查询显示每部电影和类别一行,以及电影的总租金。 window 函数在这里没有意义,因为您不想从所选行中派生任何值。

例如,如果您还想显示该类别的租金总额,可以使用 window 函数来完成:

SELECT 
  f.title AS film_title,
  c.name AS category_name,
  COUNT(*) AS count_of_film_rentals,
  SUM(COUNT(*)) OVER (PARTITION BY c.category_id) AS count_of_category_rentals
FROM film f
JOIN film_category fc ON f.film_id = fc.film_id
JOIN category c ON c.category_id = fc.category_id 
JOIN inventory i ON i.film_id = f.film_id
JOIN rental r ON r.inventory_id = i.inventory_id
WHERE c.name IN ('Animation', 'Children', 'Classics', 'Comedy', 'Family', 'Music')
GROUP BY f.film_id, c.category_id        
ORDER BY category_name, film_title;