пятница, 27 ноября 2009 г.

Аналитические функции в MySQL

Всем хорош язык MySQL, но вот в некоторых случаях надо делать запросы, которые, благодаря наличию аналитических функций, в Oracle делаются весьма просто.
Рассмотрим на примере. Скажем, есть у нас 2 таблицы: товары с полями goods_id — идентификатор, grp — группа, name — наименование, и обобщенная таблица с продажами sales с полями goods_id — идентификатор товара, period — период, summa — суммарная стоимость проданных товаров за указанный период.
И вот требуется вывести по 10 самых продаваемых товаров из каждой группы за заданный период. В Oracle запрос бы выглядел вот так:

SELECT grp, name, summa
FROM (
SELECT g.grp
,g.name
,s.summa
,row_number()
OVER (PARTITION BY g.group
ORDER BY s.summa) as rn
FROM goods g
,sales s
WHERE g.goods_id = s.sales_id
AND s.period = 2009101
)
WHERE rn <= 10
ORDER BY grp, name
А в MySQL вот так:

SET @rows_count = 0;
SET @grp = NULL;
SELECT grp, name, summa
FROM (
SELECT g.grp
,g.name
,s.summa
,CASE WHEN IFNULL(@grp, '#') != grp THEN
@rows_count := 0
END q1
,CASE WHEN IFNULL(@grp, '#') != grp THEN
@tp := tp
END q2
,@rows_count := IFNULL(@rows_count, 0) + 1 as rn
FROM goods g
,sales s
WHERE g.goods_id = s.sales_id
AND s.period = 2009101
)
WHERE rn <= 10
ORDER BY grp, name