← Назад к вопросам

Что такое row?

1.0 Junior🔥 101 комментариев
#Pandas и обработка данных#SQL и базы данных

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

ROW: строка в SQL и контексты использования

Что такое ROW в разных контекстах

ROW имеет несколько значений в зависимости от контекста:

  1. Физическая строка в таблице (обычное понимание)
  2. ROW конструктор в SQL (кортеж значений)
  3. Window функция в SQL (обработка по строкам)
  4. Концепция в данных (наблюдение/запись)

1. ROW конструктор (ROW constructor)

ROW в SQL создает кортеж значений (tuple):

-- Синтаксис
ROW(value1, value2, value3)

-- Пример 1: создать кортеж
SELECT ROW(1, 'Alice', 'alice@test.com') AS user_record;
-- Результат: (1,Alice,alice@test.com)

-- Пример 2: сравнение кортежей
SELECT *
FROM users
WHERE ROW(first_name, last_name) = ROW('Alice', 'Smith');

-- Это эквивалентно:
WHERE first_name = 'Alice' AND last_name = 'Smith';

2. ROW_NUMBER(): Window функция

ROW_NUMBER() нумерует строки в окне (partition):

-- Синтаксис
SELECT 
    ROW_NUMBER() OVER (ORDER BY column) AS row_num,
    *
FROM table;

-- Пример 1: простая нумерация
SELECT 
    ROW_NUMBER() OVER (ORDER BY created_at) AS row_num,
    user_id,
    created_at
FROM users;

-- Результат:
-- row_num | user_id | created_at
-- 1       | 5       | 2024-01-01
-- 2       | 3       | 2024-01-02
-- 3       | 1       | 2024-01-03

-- Пример 2: нумерация по группам
SELECT 
    ROW_NUMBER() OVER (PARTITION BY category ORDER BY sales DESC) AS rank_in_category,
    product_name,
    category,
    sales
FROM products;

-- Результат:
-- rank_in_category | product_name    | category   | sales
-- 1                | iPhone 15       | Electronics| 50000
-- 2                | MacBook Pro     | Electronics| 45000
-- 1                | Nike Air Max    | Fashion    | 15000
-- 2                | Adidas Ultraboost | Fashion  | 14000

3. Практические примеры ROW_NUMBER()

Пример 1: Удалить дубликаты

-- Найти дубликаты
SELECT 
    ROW_NUMBER() OVER (PARTITION BY email ORDER BY created_at) AS dup_num,
    *
FROM users;

-- Результат:
-- email              | dup_num | created_at
-- alice@test.com     | 1       | 2024-01-01  ← первый (оставить)
-- alice@test.com     | 2       | 2024-01-02  ← дубликат
-- alice@test.com     | 3       | 2024-01-03  ← дубликат
-- bob@test.com       | 1       | 2024-01-01  ← первый (оставить)

-- Удалить дубликаты (оставить только первый)
WITH ranked_users AS (
    SELECT 
        ROW_NUMBER() OVER (PARTITION BY email ORDER BY created_at) AS dup_num,
        *
    FROM users
)
DELETE FROM users
WHERE user_id IN (
    SELECT user_id FROM ranked_users WHERE dup_num > 1
);

Пример 2: Получить N-й элемент в группе

-- Топ 3 продукта по каждой категории
WITH ranked_products AS (
    SELECT 
        ROW_NUMBER() OVER (PARTITION BY category ORDER BY sales DESC) AS rank,
        product_name,
        category,
        sales
    FROM products
)
SELECT *
FROM ranked_products
WHERE rank <= 3;

Пример 3: Заказы по пользователям (последний заказ каждого)

WITH ranked_orders AS (
    SELECT 
        ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at DESC) AS order_rank,
        user_id,
        order_id,
        created_at,
        amount
    FROM orders
)
SELECT *
FROM ranked_orders
WHERE order_rank = 1;  -- последний заказ каждого пользователя

4. ROW vs RANK vs DENSE_RANK

Все три — window функции, но отличаются в обработке ties (ничьих):

SELECT 
    product_name,
    sales,
    ROW_NUMBER() OVER (ORDER BY sales DESC) AS row_num,
    RANK() OVER (ORDER BY sales DESC) AS rank,
    DENSE_RANK() OVER (ORDER BY sales DESC) AS dense_rank
FROM products;

-- Результат (если есть ties):
-- product_name | sales | row_num | rank | dense_rank
-- iPhone       | 1000  | 1       | 1    | 1
-- Samsung      | 1000  | 2       | 1    | 1  ← tie
-- Pixel        | 900   | 3       | 3    | 2  ← скачок на 3
-- MacBook      | 800   | 4       | 4    | 3

-- ROW_NUMBER: просто 1, 2, 3, 4 (непрерывно)
-- RANK: 1, 1, 3, 4 (скачок после tie)
-- DENSE_RANK: 1, 1, 2, 3 (без скачков)

5. Общее понимание ROW в анализе данных

ROW = строка (наблюдение) в датасете:

-- Каждое SELECT выбирает ROWS (строки)
SELECT * FROM users LIMIT 10;
-- Результат: 10 rows returned

-- COUNT(*) считает количество ROW'ов
SELECT COUNT(*) as total_rows FROM users;

-- GROUP BY группирует ROW'ы
SELECT category, COUNT(*) as row_count
FROM products
GROUP BY category;

6. ROW в Python/Pandas

import pandas as pd

df = pd.DataFrame({
    'user_id': [1, 2, 3],
    'name': ['Alice', 'Bob', 'Charlie'],
    'age': [25, 30, 35]
})

# Каждая строка = ROW
print(df)  # 3 rows (3 наблюдения)

# Итерация по ROW'ам
for index, row in df.iterrows():
    print(f"Row {index}: {row['name']}, age {row['age']}")
# Row 0: Alice, age 25
# Row 1: Bob, age 30
# Row 2: Charlie, age 35

# Доступ к конкретному ROW'у
row_0 = df.iloc[0]  # первая строка
print(row_0['name'])  # 'Alice'

# df.shape[0] = количество ROW'ов
print(df.shape[0])  # 3

7. Window функции: практический пример

Задача: для каждого товара найти его позицию в рейтинге по продажам

SELECT 
    product_id,
    product_name,
    category,
    sales,
    -- ROW_NUMBER по продажам (без дублирования номеров)
    ROW_NUMBER() OVER (ORDER BY sales DESC) AS overall_rank,
    -- ROW_NUMBER внутри категории
    ROW_NUMBER() OVER (PARTITION BY category ORDER BY sales DESC) AS category_rank,
    -- Средние продажи по категории
    AVG(sales) OVER (PARTITION BY category) AS category_avg_sales,
    -- Кумулятивная сумма
    SUM(sales) OVER (ORDER BY sales DESC ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS cumulative_sales
FROM products
ORDER BY sales DESC;

8. ROW конструктор для сравнений

-- Вместо этого
WHERE first_name = 'Alice' 
  AND last_name = 'Smith'
  AND email = 'alice@smith.com'

-- Можно написать так
WHERE ROW(first_name, last_name, email) = ROW('Alice', 'Smith', 'alice@smith.com')

-- Или для множественных сравнений
WHERE ROW(first_name, last_name) IN (
    ROW('Alice', 'Smith'),
    ROW('Bob', 'Jones'),
    ROW('Charlie', 'Brown')
);

9. Практический пример: Когортный анализ

-- Задача: найти, как долго пользователи остаются активными

WITH user_activity AS (
    SELECT 
        user_id,
        DATE_TRUNC('month', event_date)::DATE AS month,
        ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY DATE_TRUNC('month', event_date)) AS months_since_signup,
        COUNT(*) as events
    FROM user_events
    GROUP BY user_id, DATE_TRUNC('month', event_date)
)

SELECT 
    months_since_signup,
    COUNT(DISTINCT user_id) as active_users,
    AVG(events) as avg_events_per_user
FROM user_activity
GROUP BY months_since_signup
ORDER BY months_since_signup;

-- Результат показывает сколько пользователей активно на месяц 1, 2, 3 после signup
-- месяц | активных_юзеров | среднее_событий
-- 1      | 10000            | 25
-- 2      | 7000             | 20
-- 3      | 4200             | 15
-- (видим падение retention)

10. ROW в контексте различных БД

PostgreSQL:

SELECT ROW(1, 'test');
SELECT ROW_NUMBER() OVER (ORDER BY id);

MySQL:

SELECT ROW_NUMBER() OVER (ORDER BY id) AS rn FROM table;
-- ROW конструктор не поддерживается, используй CONCAT вместо

SQL Server:

SELECT ROW_NUMBER() OVER (ORDER BY id) AS rn FROM table;
-- ROW конструктор не поддерживается

SQLite:

SELECT ROW_NUMBER() OVER (ORDER BY id) AS rn FROM table;
-- ROW конструктор не поддерживается

Памятка для собеседования

ТерминЗначениеПример
ROWСтрока в таблицеКаждая запись данных
ROW()Конструктор кортежаROW(val1, val2) = ROW(a, b)
ROW_NUMBER()Window функция нумерацииROW_NUMBER() OVER (ORDER BY ...)
RANK()Window функция рейтинга (с пробелами)RANK() OVER (ORDER BY ...)
DENSE_RANK()Window функция рейтинга (без пробелов)DENSE_RANK() OVER (ORDER BY ...)
Rows in DataFrameНаблюдения в Pandasdf.shape[0] = количество строк

Когда использовать:

  • ✅ ROW_NUMBER(): когда нужна простая нумерация (по порядку)
  • ✅ RANK(): когда нужны рейтинги с учетом ties
  • ✅ DENSE_RANK(): когда нужны рейтинги без пробелов
  • ✅ ROW конструктор: для множественных сравнений

Важное: Row часто встречается в контексте "N-th row", "last row", "first row" — это обозначения конкретных строк в наборе данных.

Что такое row? | PrepBro