Postgres 内部连接或复杂的选择?

Postgres inner join or complicated selects?

假设我在图片中有下面的示例,预期结果在表格下方

到目前为止,我可以通过

获得出租数量
SELECT inventory.film_id,
SUM((SELECT COUNT(*) FROM rental WHERE rental.inventory_id = inventory.inventory_id)) AS rentals,
(SELECT title FROM film WHERE film.film_id = inventory.film_id) AS title
FROM inventory
GROUP BY inventory.film_id
ORDER BY inventory.film_id

结果

film_id   rentals    title
1         23         Academy Dinosaur
2          7         Ace Goldfinger
.         ..         ................

我似乎无法弄清楚如何让 category.name 从链接 film_id 到 film_category 然后到类别。我试过添加这段代码

INNER JOIN film_category ON inventory.film_id = film_category.film_id

但它只是returns相同的结果,它没有加入它。这不会像我需要的那样抓住 category.name。

如果能帮助理解此示例背后的逻辑,那就太棒了。谢谢

您可以使用 JOIN 编写简单的查询

SELECT inventory.film_id, film.title, COUNT(*) AS rentals
FROM inventory
JOIN rental ON rental.inventory_id = inventory.inventory_id
JOIN film ON film.film_id = inventory.film_id
GROUP BY inventory.film_id, film.title
ORDER BY inventory.film_id;

PostgreSQL live example

如果您需要获取电影类别,请使用下一版本:

SELECT 
    inventory.film_id, 
    film.title, 
    COUNT(DISTINCT rental_id) AS rentals, 
    ARRAY_AGG(DISTINCT category.title)
FROM inventory
JOIN rental ON rental.inventory_id = inventory.inventory_id
JOIN film ON film.film_id = inventory.film_id
JOIN film_category ON film_category.film_id = inventory.film_id
JOIN category ON film_category.category_id = category.category_id
GROUP BY inventory.film_id, film.title
ORDER BY inventory.film_id;

fiddle here

注意这里。一部电影可以有很多租借并且属于许多类别。所以你想加入出租数量和类别列表。这意味着,您应该首先汇总您的数据,然后加入:

select f.film_id, f.title, c.categories, r.number_of_rentals
from film f
left join
(
  select fc.film_id, string_agg(c.name, ', ' order by c.name) as categories
  from film_category fc
  join category c on c.category_id = fc.category_id
  group by fc.film_id
) c on c.film_id = f.film_id
left join
(
  select i.film_id, count(*) as number_of_rentals
  from rental r
  join inventory in on i.inventory_id = r.inventory_id
  group by i.film_id
) r on r.film_id = f.film_id
order by f.film_id;