窗口函数避坑指南

窗口函数避坑指南:

窗口函数执行顺序:

  • FROM
  • WHERE
  • GROUP BY
  • 聚合函数
  • HAVING
  • 窗口函数
  • SELECT
  • DISTINCT
  • UNION
  • ORDER BY
  • OFFSET
  • LIMIT

不能在WHERE子句中使用窗口函数:

错误版本演示:

SELECT 
  id, 
  final_price 
FROM auction 
WHERE final_price > AVG(final_price) OVER();

报错信息:

SELECT 
  id, 
  final_price 
FROM auction 
WHERE final_price > AVG(final_price) OVER()
> 3593 - You cannot use the window function 'avg' in this context.'
> 时间: 0.005s

正确代码:

SELECT
  id,
  final_price 
FROM (
  SELECT
    id,
    final_price,
    AVG(final_price) OVER() AS avg_final_price
  FROM auction) c
WHERE final_price > avg_final_price

不能在HAVING子句中使用窗口函数:

错误版本展示:

SELECT 
  country, 
  AVG(final_price) 
FROM auction 
GROUP BY country 
HAVING AVG(final_price) > AVG(final_price) OVER ();

正确版本展示:

SELECT
  country,
  AVG(final_price) 
FROM auction 
GROUP BY country 
HAVING AVG(final_price) > (SELECT AVG(final_price) FROM auction);

不能在GROUP BY子句中使用窗口函数:

错误版本演示:

SELECT 
  NTILE(4) OVER(ORDER BY views DESC) AS quartile, 
  MIN(views), 
  MAX(views) 
FROM auction 
GROUP BY NTILE(4) OVER(ORDER BY views DESC);

正确版本演示:

SELECT
  quartile,
  MIN(views),
  MAX(views)
FROM
  (SELECT
    views,
    ntile(4) OVER(ORDER BY views DESC) AS quartile
  FROM auction) c
GROUP BY quartile;

在ORDER BY中使用窗口函数:

SELECT
  id,
  views,
  NTILE(4) OVER(ORDER BY views DESC) AS quartile
FROM auction
ORDER BY NTILE(4) OVER(ORDER BY views DESC);

窗口函数与GROUP BY一起使用:

错误演示:

SELECT 
  category_id,
  final_price, 
  AVG(final_price) OVER() 
FROM auction;

正确演示:

SELECT
  category_id,
  MAX(final_price) AS max_final, 
  AVG(MAX(final_price)) OVER() AS `avg`
FROM auction
GROUP BY category_id;

Rank时使用聚合函数:

SELECT
  country,
  COUNT(id),
  RANK() OVER(ORDER BY COUNT(id) DESC) AS `rank`
FROM auction
GROUP BY country;

利用GROUP BY计算环比:

SELECT
  ended,
  SUM(final_price) AS sum_price,
  LAG(SUM(final_price)) OVER(ORDER BY ended) AS `lag`
FROM auction
GROUP BY ended
ORDER BY ended;

对GROUP BY分组后的数据使用 PARTITION BY:

select country,
    ended,
    sum(views) views_on_day,
    sum(sum(views))over (PARTITION BY country) views_country
from auction group by country,ended;

总结:

  • 窗口函数只能出现在SELECT和ORDER BY子句中
  • 如果查询的其他部分(WHERE,GROUP BY,HAVING)需要窗口函数,请使用子查询,然后在子查询中在使用窗口函数
  • 如果查询使用聚合或GROUP BY,请记住窗口函数只能处理分组后的结果,而不是原始的表数据
上一篇:题解 lugu P5591 小猪佩奇学数学


下一篇:Oracle中wm_concat()函数的使用