【问题标题】:Spark SQL vs Normal SQL query error without using first()不使用 first() 的 Spark SQL vs Normal SQL 查询错误
【发布时间】:2020-11-21 14:21:54
【问题描述】:

我试图在 Spark SQL 中运行一个简单的查询,但除非我使用 first(),否则它会抛出错误

此查询在 MySQL 中正常工作

SELECT film.title,count(rental.rental_id) as total_rentals, film.rental_rate, count(rental.rental_id) * film.rental_rate as revenue
FROM rental
         INNER JOIN inventory ON rental.inventory_id = inventory.inventory_id
         INNER JOIN film ON inventory.film_id = film.film_id
GROUP BY film.title
ORDER BY 1

但 Spark SQL 不一样 我得到的错误是:

Exception in thread "main" org.apache.spark.sql.AnalysisException: expression 'film.`rental_rate`' is neither present in the group by, nor is it an aggregate function. Add to group by or wrap in first() (or first_value) if you don't care which value you get.;;

这样做实际上可以解决问题

SELECT  film.title,count(rental.rental_id) as total_rentals, first(film.rental_rate), count(rental.rental_id) * first(film.rental_rate) as revenue
FROM rental
INNER JOIN inventory ON rental.inventory_id = inventory.inventory_id
INNER JOIN film ON inventory.film_id = film.film_id
GROUP BY film.title
ORDER BY 1

有人能解释一下为什么需要 Spark SQL 吗?

【问题讨论】:

    标签: mysql sql group-by apache-spark-sql


    【解决方案1】:

    SQL 中有一个共同要求,即group by 查询中的所有非聚合列都必须出现在group by 子句中。一些数据库理解功能依赖列的概念,并允许您将主键列仅放在 group by 子句中。

    我猜title 不是film 的主键,所以你原来的查询不是有效的标准SQL。我怀疑您在 MySQL 中运行它,它(唉!)具有允许禁用标准要求的选项。

    在支持group by 中的函数依赖的数据库中,您可以将查询分阶段为:

    SELECT f.title, count(*) as total_rentals, f.rental_rate, count(*) * f.rental_rate as revenue
    FROM rental r
    INNER JOIN inventory i ON r.inventory_id = i.inventory_id
    INNER JOIN film f ON i.film_id = f.film_id
    GROUP BY f.film_id
    ORDER BY 1
    

    我认为 Spark 不会理解这一点,所以只需将所有需要的列添加到 group by 子句:

    SELECT f.title, count(*) as total_rentals, f.rental_rate, count(*) * f.rental_rate as revenue
    FROM rental r
    INNER JOIN inventory i ON r.inventory_id = i.inventory_id
    INNER JOIN film f ON i.film_id = f.film_id
    GROUP BY f.film_id, f.title, f.rental_rate
    ORDER BY 1
    

    注意事项:

    • group by 子句中包含film_id 仍然是一个好习惯;在现实生活中,两部不同的电影可能具有相同的标题和评分,您不想将它们组合在一起

    • count(r.rental_id) 可以简化为count(*)(因为显然该列不能是null

    • 表别名使查询更易于编写和阅读

    【讨论】:

    • 感谢您的快速反馈。那么对于 MySQL 等,它会在后台自动完成?
    【解决方案2】:

    我怀疑你想要:

    SELECT f.title, COUNT(*) as total_rentals, f.rental_rate,  
           SUM(f.rental_rate) as revenue
    FROM rental r JOIN
         inventory i
         ON r.inventory_id = i.inventory_id JOIN
         film f
         ON i.film_id = f.film_id
    GROUP BY f.title, f.rental_rate
    ORDER BY 1;
    

    注意事项:

    • 一般来说,GROUP BY 列应该是SELECT 中的未聚合列。在过去的几年里,这甚至在 MySQL 中是必需的(使用默认设置)。
    • 您可以对rental_rate 列求和。无需计数和乘法。
    • 表别名使查询更易于编写和阅读。

    第一个 SQL 在 MySQL 中起作用是因为 MySQL 扩展了 SQL 语法以允许它。 SparkSQL(在这种情况下)正在做几乎所有其他数据库所做的事情。

    【讨论】:

    猜你喜欢
    • 2019-12-07
    • 1970-01-01
    • 2017-04-23
    • 2021-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-29
    相关资源
    最近更新 更多