DBAtlas · Атлас эксплуатации баз данных

Оконные функции (ROW_NUMBER/RANK/LAG)

Oracle

-- Rank by amount within each city and fetch the previous value:
SELECT city, name, amount,
  ROW_NUMBER() OVER (PARTITION BY city ORDER BY amount DESC) AS row_num,
  RANK()       OVER (PARTITION BY city ORDER BY amount DESC) AS rnk,
  LAG(amount)   OVER (PARTITION BY city ORDER BY created_at)      AS prev_amount
FROM sale;

Oracle — пионер аналитических (оконных) функций; ROW_NUMBER, RANK, DENSE_RANK, LAG, LEAD, SUM/AVG OVER, NTILE и FIRST_VALUE полностью поддерживаются. Внутри OVER PARTITION BY задаёт группы, ORDER BY — порядок, а рамка (ROWS/RANGE BETWEEN) — скользящее окно.

PostgreSQL

-- Window functions with OVER():
SELECT city, name, amount,
  ROW_NUMBER() OVER (PARTITION BY city ORDER BY amount DESC) AS row_num,
  RANK()       OVER (PARTITION BY city ORDER BY amount DESC) AS rnk,
  LAG(amount)   OVER (PARTITION BY city ORDER BY created_at)      AS prev_amount
FROM sale;

PostgreSQL полностью поддерживает оконные функции со стандартным синтаксисом SQL. Доступны ROW_NUMBER/RANK/DENSE_RANK, LAG/LEAD, агрегаты с OVER, NTILE и FIRST_VALUE/LAST_VALUE. Повторяющиеся определения окон можно именовать и переиспользовать через предложение WINDOW.

MySQL

-- MySQL 8.0+ window functions:
SELECT city, name, amount,
  ROW_NUMBER() OVER (PARTITION BY city ORDER BY amount DESC) AS row_num,
  RANK()       OVER (PARTITION BY city ORDER BY amount DESC) AS rnk,
  LAG(amount)   OVER (PARTITION BY city ORDER BY created_at)      AS prev_amount
FROM sale;

MySQL добавил оконные функции в версии 8.0 (MariaDB 10.2+ их тоже поддерживает). Доступны ROW_NUMBER, RANK, DENSE_RANK, LAG, LEAD, NTILE и агрегаты с OVER. В версиях до 8.0 этих функций нет; раньше их эмулировали пользовательскими переменными.

SQL Server

-- Window functions with OVER():
SELECT city, name, amount,
  ROW_NUMBER() OVER (PARTITION BY city ORDER BY amount DESC) AS row_num,
  RANK()       OVER (PARTITION BY city ORDER BY amount DESC) AS rnk,
  LAG(amount)   OVER (PARTITION BY city ORDER BY created_at)      AS prev_amount
FROM dbo.sale;

SQL Server поддерживает оконные функции с 2005 (ROW_NUMBER/RANK) и 2012 (LAG/LEAD, рамки, агрегаты с OVER). PARTITION BY, ORDER BY и рамка ROWS/RANGE полностью доступны. Для постраничного вывода обычно используют OFFSET/FETCH или ROW_NUMBER.

MongoDB

// Window calculations with $setWindowFields:
db.sale.aggregate([
  { $setWindowFields: {
      partitionBy: "$city",
      sortBy: { amount: -1 },
      output: {
        row_num: { $documentNumber: {} },
        rnk: { $rank: {} },
        prev_amount: { $shift: { output: "$amount", by: -1 } }
      }
  } }
])

Этап агрегации $setWindowFields, появившийся в MongoDB 5.0, обеспечивает оконные функции: $documentNumber (ROW_NUMBER), $rank/$denseRank, $shift (LAG/LEAD), агрегатные функции и скользящие окна (window: { documents/range }). partitionBy и sortBy соответствуют PARTITION BY/ORDER BY в SQL.

Redis

# Not applicable: there are no SQL-like window functions.

Redis — хранилище ключ-значение; аналитических оконных функций нет. Для упорядоченных результатов можно использовать Sorted Set (доступ по рангу через ZADD/ZRANGE); однако реляционные оконные операции вроде PARTITION BY/LAG выполняются на уровне приложения.

Elasticsearch

# Not applicable: there are no SQL-like window functions.
# Closest equivalent: bucket aggregations.
GET sale/_search
{ "size": 0, "aggs": { "by_city": {
  "terms": { "field": "city" },
  "aggs": { "total": { "sum": { "field": "amount" } } } } } }

Elasticsearch не предлагает классических оконных функций (ROW_NUMBER/RANK/LAG). Группировка и упорядочение выполняются через фреймворк агрегаций: агрегация terms близка к PARTITION BY, top_hits — к верхним записям, а derivative/serial_diff (pipeline-агрегации) — к последовательным разностям вроде LAG.

Открыть в DBAtlas →