OVER (...) turns an aggregate into a window function that answers on every row instead of collapsing them. OVER () is one window over the whole result; PARTITION BY splits it into independent windows, like GROUP BY without the collapse:
SELECT category_id AS cat, sku, price,
ROUND(AVG(price) OVER (PARTITION BY category_id), 2) AS cat_avg,
ROUND(100 * price / SUM(price) OVER (), 1) AS pct
FROM products WHERE category_id IN (2, 5) ORDER BY cat, price DESC;Output
+-----+-----------+-------+---------+------+ | cat | sku | price | cat_avg | pct | +-----+-----------+-------+---------+------+ | 2 | BK-LAR-01 | 49.00 | 43.63 | 33.0 | | 2 | BK-LNX-01 | 42.00 | 43.63 | 28.3 | | 2 | BK-PHP-01 | 39.90 | 43.63 | 26.9 | | 5 | AC-MUG-01 | 12.50 | 8.75 | 8.4 | | 5 | AC-STK-01 | 4.99 | 8.75 | 3.4 | +-----+-----------+-------+---------+------+ 5 rows in set (0.001 sec)
The shares total 100 over these five rows, not the catalog: windows run after WHERE, GROUP BY and HAVING (SELECT Execution Order). So RANK() OVER (...) in WHERE fails with ERROR 3593 (HY000): You cannot use the window function 'rank' in this context.; compute it in a CTE and filter outside. COUNT(DISTINCT ...) OVER and a windowed GROUP_CONCAT fail with error 1235.