When should I use a window function instead of GROUP BY?
Use GROUP BY when you want fewer rows than you started with, and a window function when you want the same rows with extra columns attached.
That sounds simple, but the practical consequences are bigger than they look. A GROUP BY query produces one row per group, so any column that is not the grouping key has to be aggregated. A window function keeps every row, so you can show the row's own values and the group summary side by side without one destroying the other.
Three situations where the window function is the better tool. Keeping detail rows while showing their group total — the order list with the customer's total next to each order. Comparing each row to its group — the order next to the customer's average, or the month's revenue next to the year-to-date figure. And ranking within a group — the top three orders per customer — which a GROUP BY simply cannot express.
There are also cases where GROUP BY is the right answer, and pretending otherwise makes a query slower. If you only need the summary and no detail, GROUP BY produces strictly less data, and the engine does less work. A window function that computes a total over a partition and then discards all but one row per partition is a GROUP BY written the expensive way.
One more consideration: the two can be combined. Aggregate to a grain with GROUP BY, then use a window function over that result — that is exactly how a running total over monthly revenue is built, with a CTE that groups by month and a window function that runs over the months.