[英]RANK OVER PARTITION BY on aggregate functions
Here is a set of 3 tables:这是一组 3 个表:
Orders (ORDER_ID, CUSTOMER_ID, ORDER_DATE)
订单(ORDER_ID, CUSTOMER_ID, ORDER_DATE)
Order detail (ORDER_ID, PRODUCT_ID, PRICE, UNITS)
订单详细信息(ORDER_ID, PRODUCT_ID, PRICE, UNITS)
Customers (CUSTOMER_ID, SIGNUP_DATE, COUNTRY)
客户(CUSTOMER_ID, SIGNUP_DATE, COUNTRY)
I need to identify the top 3 months, by revenue, for each country.我需要按收入确定每个国家/地区的前 3 个月。 This is the query that I thought of:这是我想到的查询:
SELECT c.country
, MONTH(o.order_date) as _Month
, SUM(od.price * od.units) AS revenue
, RANK() OVER (PARTITION BY country, _Month ORDER BY revenue) AS Rank
FROM orders o
LEFT JOIN customers c ON o.customer_id = c.customer_id
JOIN order_detail od
WHERE o.order_id = od.order_id GROUP BY country, Month
HAVING Rank <= 3
Will this query work because I am not sure if SUM(od.price * od.units) as revenue
can be used in the RANK() OVER function or not since it's an aggregate function?这个查询是否有效,因为我不确定SUM(od.price * od.units) as revenue
可以用于 RANK() OVER 函数,因为它是一个聚合函数?
In databases that support window functions, this would normally be written as:在支持窗口函数的数据库中,这通常写为:
SELECT cm.*
FROM (SELECT c.country, MONTH(o.order_date) as Month, SUM(od.price * od.units) AS revenue,
RANK() OVER (PARTITION BY country, MONTH(o.order_date) ORDER BY SUM(od.price * od.units) ) AS Rank
FROM orders o LEFT JOIN
customers c
ON o.customer_id = c.customer_id JOIN
order_detail od
ON o.order_id = od.order_id
GROUP BY country, Month
) cm
HAVING Rank <= 3;
This is meant to be more Comment than Answer, since I can format a bit prettier down here, but the typical query logical order of operations goes something along the lines of:这意味着更多的评论而不是答案,因为我可以在这里格式化更漂亮,但典型的查询逻辑操作顺序大致如下:
FROM
is built first. FROM
首先构建。 JOIN
s will be applied.将应用JOIN
。 WHERE
will cause the above tables to be filtered GROUP BY
and aggregates
will be applied. WHERE
将导致上面的表被过滤GROUP BY
并应用aggregates
。 HAVING
is applied.应用了HAVING
。 WINDOW FUNCTION
s will be calculated.将计算WINDOW FUNCTION
s。 These operate outside of the ORDER BY
SELECT
will be applied.这些在ORDER BY
SELECT
之外的操作将被应用。 DISTINCT
will be applied.将应用DISTINCT
。 ORDER BY
will be applied. ORDER BY
将被应用。 TOP
/ LIMIT
will be applied. TOP
/ LIMIT
将被应用。
In general, anything that happens in a step will be available to the steps following it (ie a SELECT
alias can be used in the ORDER BY
but not in the GROUP BY
. But in MySQL, the HAVING
can use aliases defined in the SELECT
. Of course, the optimizer can always decide to do its own thing and may choose a different order, but this is what usually happens in most flavors of SQL.一般来说,在一个步骤中发生的任何事情都可以用于它之后的步骤(即SELECT
别名可以在ORDER BY
使用,但不能在GROUP BY
。但在 MySQL 中, HAVING
可以使用SELECT
定义的别名。当然,优化器总是可以决定做自己的事情,也可以选择不同的顺序,但这通常发生在大多数 SQL 风格中。
A couple of references I have are MS SQL related, but, for the most part, still apply to other types:我拥有的一些参考资料与 MS SQL 相关,但在大多数情况下,仍然适用于其他类型:
https://blog.sqlauthority.com/2009/10/10/sql-server-download-logical-query-processing-poster/ https://blog.sqlauthority.com/2009/10/10/sql-server-download-logical-query-processing-poster/
Confused about Itzik Ben-Gan's Logical Query Processing order in his SQL Server 2005 book and SQL Server 2008 book 对 Itzik Ben-Gan 在他的 SQL Server 2005 book 和 SQL Server 2008 book 中的 Logical Query Processing order 感到困惑
https://accessexperts.com/wp-content/uploads/2015/07/Logical-Query-Processing-Poster.pdf https://accessexperts.com/wp-content/uploads/2015/07/Logical-Query-Processing-Poster.pdf
https://www.brentozar.com/archive/2015/07/logical-query-processing/ https://www.brentozar.com/archive/2015/07/logical-query-processing/
I don't think Gordon Linoff's answer is right.我认为 Gordon Linoff 的回答不正确。
(1) You can not directly call the alias in the Rank() function, which has been mentioned by Gordon (1) Rank()函数中不能直接调用别名,Gordon已经提到过
(2) For your use case, you want to rank the months within each country, the rank part should be (2) 对于你的用例,你想对每个国家的月份进行排名,排名部分应该是
RANK() OVER (PARTITION BY country ORDER BY SUM(od.price * od.units) ) AS Rank
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.