SQL窗口函数和连接

Posted

技术标签:

【中文标题】SQL窗口函数和连接【英文标题】:SQL window function and joins 【发布时间】:2021-01-24 06:00:25 【问题描述】:

我的查询如下:

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

结果如下:

正如您所见,电影的标题是重复的,正如您已经知道的那样,它不应该重复。但是,我不明白为什么会这样?

答案其实应该如上图。

非常感谢任何帮助。

【问题讨论】:

您的一个联接是使行相乘,一次取出一个,看看是哪一个。猜测rental 不使用group by 会导致问题,而且每部电影也可以有多个类别 只需在最外层的select 子句之后添加distinct @KoushikRoy OP 应该在没有首先了解为什么返回多行的情况下执行DISTINCT :) 同意,抱歉,我认为 OP 知道数据。 您没有显示真正的查询。您显示的查询无效。缺少 GROUP BY 子句。 【参考方案1】:

为什么会这样?这就是窗口函数的作用。它们不会减少行数。在现有行上添加新列(通常包含从多行收集的数据)。

您只需要一个聚合:

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

【讨论】:

感谢所有帮助回答我问题的人!你们是最棒的!

以上是关于SQL窗口函数和连接的主要内容,如果未能解决你的问题,请参考以下文章

Hive sql及窗口函数

重学SQL窗口函数

窗口函数问题 - 分区最大

将多个 self JOIN 转换为窗口函数或子查询 (SQL)

SQL窗口函数

SQL窗口函数