SQL задачи

0.0(0)
studied byStudied by 3 people
learnLearn
examPractice Test
spaced repetitionSpaced Repetition
heart puzzleMatch
flashcardsFlashcards
Card Sorting

1/68

encourage image

There's no tags or description

Looks like no tags are added yet.

Study Analytics
Name
Mastery
Learn
Test
Matching
Spaced

No study sessions yet.

69 Terms

1
New cards

Как найти дубликат столбца email в таблице users?

Один из самых распространенных и эффективных методов — это использование SQL-запроса с функцией GROUP BY и условием HAVING.

SELECT email, COUNT(*)
FROM users
GROUP BY email
HAVING COUNT(*) > 1;
  • GROUP BY email: Группирует записи в таблице users по значению в колонке email.

  • COUNT(*): Подсчитывает количество записей в каждой группе.

  • HAVING COUNT(*) > 1: Оставляет только те группы, где количество записей больше одного, то есть, те, где есть дубликаты.

2
New cards

Как найти и удалить дубликат столбца email в таблице users?

Сначала нужно определить, какие записи содержат дублирующиеся email. Для этого можно использовать следующий запрос:

SELECT email, COUNT(*) 
FROM users
GROUP BY email
HAVING COUNT(*) > 1;

Потом удалить дубликаты. Для удаления дубликатов можно использовать CTE (Common Table Expressions) и оператор DELETE. Например:

WITH duplicates AS (
    SELECT id
    FROM (
        SELECT id, ROW_NUMBER() OVER (PARTITION BY email ORDER BY id) AS row_num
        FROM users
    ) t
    WHERE t.row_num > 1
)
DELETE FROM users
WHERE id IN (SELECT id FROM duplicates);

Этот запрос:

  • Внутренний запрос ROW_NUMBER() OVER (PARTITION BY email ORDER BY id) присваивает каждой записи порядковый номер внутри группы одинаковых email.

  • Запрос WHERE row_num > 1 выбирает все записи, начиная со второй в каждой группе.

  • Внешний запрос удаляет все записи, идентификаторы которых попали в список дубликатов.

3
New cards

У вас есть таблица с товарами

product_id

quantity

1

10

2

5

1

15

2

20

Мы хотим узнать общее количество проданных единиц для каждого продукта. Напишите запрос и объясните что вы получите

SELECT product_id, SUM(quantity) AS total_quantity
FROM sales
GROUP BY product_id;
  • Группировка: GROUP BY product_id берет все строки, где product_id одинаков, и собирает их в одну группу. В данном случае, все строки с product_id = 1 будут в одной группе, а все строки с product_id = 2 будут в другой группе.

  • Агрегирование: Затем SUM(quantity) вычисляет сумму quantity для каждой группы. Для product_id = 1 сумма будет 10 + 15 = 25, а для product_id = 2 — 5 + 20 = 25.

Результат запроса:

product_id

total_quantity

1

25

2

25

GROUP BY позволяет объединить строки с одинаковыми значениями в один набор и затем применять агрегатные функции (такие как сумма, среднее значение) к этим группам. Это полезно для получения обобщенной информации из данных.

4
New cards

Описание задачи: У вас есть таблица sales, содержащая записи о продажах. Вам нужно найти общую сумму продаж для каждого продукта.

Таблица sales:

product_id

sale_date

amount

1

2024-01-01

100

2

2024-01-02

200

1

2024-01-03

150

3

2024-01-04

300

2

2024-01-05

250

SELECT product_id, SUM(amount) AS total_sales
FROM sales
GROUP BY product_id;

Результат:

product_id

total_sales

1

250

2

450

3

300

Объяснение: GROUP BY product_id группирует записи по product_id, то есть собирает все продажи для каждого продукта вместе. Функция SUM(amount) вычисляет сумму продаж для каждой группы. Результат показывает общую сумму продаж по каждому продукту.

5
New cards

Описание задачи: Найдите все продукты, у которых общая сумма продаж превышает 400.

Таблица sales:

product_id

sale_date

amount

1

2024-01-01

100

2

2024-01-02

200

1

2024-01-03

150

3

2024-01-04

300

2

2024-01-05

250

SELECT product_id, SUM(amount) AS total_sales
FROM sales
GROUP BY product_id
HAVING SUM(amount) > 400;

Результат:

product_id

total_sales

2

450

3

300

Объяснение: GROUP BY product_id группирует записи по продуктам. HAVING SUM(amount) > 400 фильтрует группы, оставляя только те, у которых общая сумма продаж больше 400. В данном случае продукт с product_id = 2 и product_id = 3 удовлетворяют этому условию.

6
New cards

Описание задачи: Найдите среднюю зарплату по каждому отделу.

Таблица employees:

employee_id

department

salary

1

Sales

5000

2

HR

4500

3

Sales

6000

4

HR

4000

5

IT

5500

SELECT department, AVG(salary) AS average_salary
FROM employees
GROUP BY department;

Результат:

department

average_salary

Sales

5500

HR

4250

IT

5500

Объяснение: GROUP BY department группирует сотрудников по отделам. Функция AVG(salary) вычисляет среднюю зарплату для каждой группы. Результат показывает среднюю зарплату в каждом отделе.

7
New cards

Описание задачи: Найдите все отделы, в которых минимальная зарплата сотрудников ниже 3000.

Таблица employees:

employee_id

department

salary

1

Sales

5000

2

HR

4500

3

Sales

2500

4

HR

4000

5

IT

5500

SELECT department, MIN(salary) AS min_salary
FROM employees
GROUP BY department
HAVING MIN(salary) < 3000;

Результат:

department

min_salary

Sales

2500

Объяснение: GROUP BY department группирует сотрудников по отделам. HAVING MIN(salary) < 3000 фильтрует группы, оставляя только те, где минимальная зарплата ниже 3000. В данном случае только отдел Sales удовлетворяет этому условию.

8
New cards

Описание задачи: Найдите количество заказов для каждого клиента.

Таблица orders:

order_id

customer_id

order_date

1

101

2024-01-01

2

102

2024-01-02

3

101

2024-01-03

4

103

2024-01-04

5

102

2024-01-05

SELECT customer_id, COUNT(order_id) AS order_count
FROM orders
GROUP BY customer_id;

Результат:

customer_id

order_count

101

2

102

2

103

1

Объяснение: GROUP BY customer_id группирует заказы по клиентам. COUNT(order_id) подсчитывает количество заказов для каждого клиента. Результат показывает количество заказов для каждого клиента.

9
New cards

Описание задачи: Найдите продукты с наибольшим количеством продаж и отсортируйте их по убыванию.

Таблица sales:

product_id

sale_date

quantity

1

2024-01-01

50

2

2024-01-02

20

1

2024-01-03

30

3

2024-01-04

40

2

2024-01-05

10

SELECT product_id, SUM(quantity) AS total_quantity
FROM sales
GROUP BY product_id
ORDER BY total_quantity DESC;

Результат:

product_id

total_quantity

1

80

3

40

2

30

Объяснение: GROUP BY product_id группирует продажи по продуктам. SUM(quantity) вычисляет общее количество продаж для каждого продукта. ORDER BY total_quantity DESC сортирует результаты по убыванию общего количества продаж, чтобы сначала отображались продукты с наибольшими продажами.

10
New cards

Описание задачи: Найдите среднюю зарплату в отделах, где есть работники с зарплатой выше 7000.

Таблица employees:

employee_id

department

salary

1

Sales

8000

2

HR

4500

3

Sales

6000

4

HR

4000

5

IT

7500

SELECT department, AVG(salary) AS average_salary
FROM employees
WHERE salary > 7000
GROUP BY department;

Результат:

department

average_salary

Sales

8000

IT

7500

Объяснение: WHERE salary > 7000 фильтрует сотрудников с зарплатой выше 7000. GROUP BY department группирует оставшиеся записи по отделам. AVG(salary) вычисляет среднюю зарплату для каждой группы. Результат показывает среднюю зарплату в отделах, где есть сотрудники с высокой зарплатой.

11
New cards

Описание задачи: Используйте таблицу orders, чтобы найти количество заказов на каждого клиента за последние 30 дней.

Таблица orders:

order_id

customer_id

order_date

1

101

2024-07-01

2

102

2024-07-10

3

101

2024-07-15

4

103

2024-07-20

5

102

2024-07-25

SELECT customer_id, COUNT(order_id) AS order_count
FROM orders
WHERE order_date >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY customer_id;

Результат:

customer_id

order_count

101

2

102

2

103

1

Объяснение: WHERE order_date >= CURRENT_DATE - INTERVAL '30 days' фильтрует заказы, сделанные за последние 30 дней. GROUP BY customer_id группирует заказы по клиентам. COUNT(order_id) подсчитывает количество заказов для каждого клиента за указанный период. Результат показывает количество заказов на каждого клиента за последние 30 дней.

12
New cards

Описание задачи: У вас есть таблица employees. Найдите ранг каждого сотрудника по зарплате внутри его отдела.

Таблица employees:

employee_id

department

salary

1

Sales

5000

2

HR

4500

3

Sales

6000

4

HR

4000

5

IT

5500

SELECT employee_id, department, salary,
       ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS salary_rank
FROM employees;

Результат:

employee_id

department

salary

salary_rank

3

Sales

6000

1

1

Sales

5000

2

2

HR

4500

1

4

HR

4000

2

5

IT

5500

1

Объяснение: ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) присваивает уникальный ранг каждому сотруднику в пределах их отдела, основываясь на зарплате в порядке убывания. Результат показывает, как сотрудники ранжируются по зарплате внутри каждого отдела.

13
New cards

Описание: Найдите кумулятивную сумму продаж по каждому продукту по мере продвижения во времени.

Таблица sales:

sale_date

product_id

amount

2024-01-01

1

100

2024-01-02

1

150

2024-01-03

2

200

2024-01-04

1

50

2024-01-05

2

100

SELECT sale_date, product_id, amount,
       SUM(amount) OVER (PARTITION BY product_id ORDER BY sale_date) AS cumulative_sum
FROM sales;

sale_date

product_id

amount

cumulative_sum

2024-01-01

1

100

100

2024-01-02

1

150

250

2024-01-04

1

50

300

2024-01-03

2

200

200

2024-01-05

2

100

300

Объяснение: Функция SUM() вычисляет кумулятивную сумму amount для каждого product_id по мере продвижения во времени (sale_date). Сумма увеличивается по мере добавления новых значений.

14
New cards

Описание: Выведите уникальный номер каждой строке в таблице, упорядоченной по дате продажи.

Таблица sales:

sale_date

product_id

amount

2024-01-01

1

100

2024-01-15

1

150

2024-01-25

2

200

2024-02-01

2

50

SELECT sale_date, product_id, amount,
       ROW_NUMBER() OVER (ORDER BY sale_date) AS row_number
FROM sales;

Результат:

sale_date

product_id

amount

row_number

2024-01-01

1

100

1

2024-01-15

1

150

2

2024-01-25

2

200

3

2024-02-01

2

50

4

Объяснение: Функция ROW_NUMBER() назначает уникальный номер каждой строке, упорядоченной по sale_date.

15
New cards

Описание: Назначьте уникальный ранг каждому сотруднику в зависимости от его зарплаты в каждой компании.

Таблица employees:

employee_id

company_id

salary

1

1

5000

2

1

6000

3

1

7000

4

2

4500

5

2

5500

SELECT employee_id, company_id, salary,
       ROW_NUMBER() OVER (PARTITION BY company_id ORDER BY salary DESC) AS rank
FROM employees;

Результат:

employee_id

company_id

salary

rank

3

1

7000

1

2

1

6000

2

1

1

5000

3

5

2

5500

1

4

2

4500

2

Объяснение: Функция ROW_NUMBER() нумерует сотрудников внутри каждой компании (company_id), упорядоченных по salary в убывающем порядке.

16
New cards

Описание: Найдите номер заказа для каждого клиента, упорядоченный по дате заказа.

Таблица orders:

order_date

customer_id

order_id

2024-01-01

1

101

2024-01-05

1

102

2024-01-10

2

201

2024-01-15

2

202

SELECT order_date, customer_id, order_id,
       ROW_NUMBER() OVER (PARTITION BY customer_id ORDER BY order_date) AS order_number
FROM orders;

Результат:

order_date

customer_id

order_id

order_number

2024-01-01

1

101

1

2024-01-05

1

102

2

2024-01-10

2

201

1

2024-01-15

2

202

2

Объяснение: ROW_NUMBER() нумерует заказы каждого клиента в порядке возрастания order_date.

17
New cards

Описание: Назначьте уникальный номер каждой транзакции клиента, упорядоченный по дате транзакции.

Таблица transactions:

transaction_date

client_id

transaction_id

2024-01-01

1

1001

2024-01-02

1

1002

2024-01-03

2

2001

2024-01-04

2

2002

SELECT transaction_date, client_id, transaction_id,
       ROW_NUMBER() OVER (PARTITION BY client_id ORDER BY transaction_date) AS transaction_number
FROM transactions;

Результат:

transaction_date

client_id

transaction_id

transaction_number

2024-01-01

1

1001

1

2024-01-02

1

1002

2

2024-01-03

2

2001

1

2024-01-04

2

2002

2

Объяснение: ROW_NUMBER() нумерует транзакции внутри каждой группы клиентов (client_id) по дате транзакции в порядке возрастания.

18
New cards

Описание: Ранжируйте студентов по их оценкам в каждом курсе.

Таблица student_grades:

student_id

course_id

grade

1

1

90

2

1

85

3

1

88

4

2

92

5

2

91

SELECT student_id, course_id, grade,
       ROW_NUMBER() OVER (PARTITION BY course_id ORDER BY grade DESC) AS grade_rank
FROM student_grades;

Результат:

student_id

course_id

grade

grade_rank

1

1

90

1

3

1

88

2

2

1

85

3

4

2

92

1

5

2

91

2

Объяснение: ROW_NUMBER() ранжирует студентов по их оценкам в каждом курсе (course_id), начиная с самой высокой оценки.

19
New cards

Описание: Ранжируйте сотрудников по их зарплате внутри каждого отдела, не пропуская ранги для сотрудников с одинаковыми зарплатами.

Таблица employees:

employee_id

department_id

salary

1

1

60000

2

1

60000

3

1

50000

4

2

70000

5

2

65000

6

2

65000

SELECT employee_id, department_id, salary,
       DENSE_RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) AS salary_rank
FROM employees;

Результат:

employee_id

department_id

salary

salary_rank

1

1

60000

1

2

1

60000

1

3

1

50000

2

4

2

70000

1

5

2

65000

2

6

2

65000

2

Объяснение: DENSE_RANK() назначает одинаковый ранг сотрудникам с одинаковой зарплатой в пределах одного отдела. Ранги не пропускаются, даже если несколько сотрудников имеют одинаковую зарплату.

20
New cards

Описание: Ранжируйте заказы по их сумме внутри каждого месяца, не пропуская ранги при одинаковых суммах.

Таблица orders:

order_id

order_date

amount

1

2024-01-05

500

2

2024-01-10

300

3

2024-01-15

500

4

2024-02-05

700

5

2024-02-10

600

6

2024-02-15

600

SELECT order_id, order_date, amount,
       DENSE_RANK() OVER (PARTITION BY DATE_TRUNC('month', order_date) ORDER BY amount DESC) AS amount_rank
FROM orders;

Результат:

order_id

order_date

amount

amount_rank

1

2024-01-05

500

1

3

2024-01-15

500

1

2

2024-01-10

300

2

4

2024-02-05

700

1

5

2024-02-10

600

2

6

2024-02-15

600

2

Объяснение: DENSE_RANK() ранжирует заказы по сумме в пределах каждого месяца. Суммы, равные друг другу, получают одинаковый ранг, и следующие ранги не пропускаются.

21
New cards

Описание: Ранжируйте продукты по количеству продаж в каждом квартале, не пропуская ранги при одинаковых количествах.

Таблица sales:

product_id

sale_date

quantity

1

2024-01-15

100

2

2024-01-20

150

1

2024-02-10

100

2

2024-02-15

150

3

2024-03-05

200

SELECT product_id, sale_date, quantity,
       DENSE_RANK() OVER (PARTITION BY DATE_TRUNC('quarter', sale_date) ORDER BY quantity DESC) AS sales_rank
FROM sales;

Результат:

product_id

sale_date

quantity

sales_rank

1

2024-01-15

100

2

2

2024-01-20

150

1

1

2024-02-10

100

2

2

2024-02-15

150

1

3

2024-03-05

200

1

Объяснение: DENSE_RANK() используется для ранжирования продуктов по количеству продаж в пределах каждого квартала. Продукты с одинаковым количеством продаж получают одинаковый ранг.

22
New cards

Описание: Ранжируйте сотрудников по времени отклика на запросы, не пропуская ранги при одинаковых значениях времени отклика.

Таблица responses:

employee_id

response_time

1

15

2

10

3

15

4

20

5

10

SELECT employee_id, response_time,
       DENSE_RANK() OVER (ORDER BY response_time) AS response_rank
FROM responses;

Результат:

employee_id

response_time

response_rank

2

10

1

5

10

1

1

15

2

3

15

2

4

20

3

Объяснение: DENSE_RANK() присваивает ранги сотрудникам на основе их времени отклика, где наименьшее время получает ранг 1, и одинаковые времена отклика получают одинаковый ранг.

23
New cards

Описание: Ранжируйте продавцов по количеству сделанных продаж в каждый месяц, не пропуская ранги при одинаковом числе продаж.

Таблица sales_reps:

sales_rep_id

month

sales_count

1

2024-01-01

30

2

2024-01-01

45

3

2024-01-01

30

4

2024-02-01

50

5

2024-02-01

50

6

2024-02-01

25

SELECT sales_rep_id, month, sales_count,
       DENSE_RANK() OVER (PARTITION BY month ORDER BY sales_count DESC) AS sales_rank
FROM sales_reps;

Результат:

sales_rep_id

month

sales_count

sales_rank

2

2024-01-01

45

1

1

2024-01-01

30

2

3

2024-01-01

30

2

4

2024-02-01

50

1

5

2024-02-01

50

1

6

2024-02-01

25

2

Объяснение: DENSE_RANK() присваивает ранги продавцам по количеству сделанных продаж в каждом месяце. Продавцы с одинаковым числом продаж получают одинаковый ранг, и следующий ранг идет без пропусков.

24
New cards

Описание: Ранжируйте фильмы по их рейтингам в каждом жанре, не пропуская ранги при одинаковых рейтингах.

Таблица movies:

movie_id

genre

rating

1

Action

8.5

2

Action

9.0

3

Action

8.5

4

Comedy

7.0

5

Comedy

8.0

6

Comedy

8.0

SELECT movie_id, genre, rating,
       DENSE_RANK() OVER (PARTITION BY genre ORDER BY rating DESC) AS rating_rank
FROM movies;

Результат:

movie_id

genre

rating

rating_rank

2

Action

9.0

1

1

Action

8.5

2

3

Action

8.5

2

5

Comedy

8.0

1

6

Comedy

8.0

1

4

Comedy

7.0

2

Объяснение: DENSE_RANK() назначает ранги фильмам в каждом жанре по их рейтингам, при этом одинаковые рейтинги получают одинаковый ранг.

25
New cards

Описание: Ранжируйте сотрудников по количеству проектов, в которых они участвуют, не пропуская ранги при одинаковом количестве проектов.

Таблица employee_projects:

employee_id

project_id

1

101

1

102

2

101

2

103

3

101

3

102

3

103

SELECT employee_id, COUNT(project_id) AS project_count,
       DENSE_RANK() OVER (ORDER BY COUNT(project_id) DESC) AS project_rank
FROM employee_projects
GROUP BY employee_id;

Результат:

employee_id

project_count

project_rank

3

3

1

1

2

2

2

2

2

Объяснение: DENSE_RANK() используется для ранжирования сотрудников по количеству проектов. Сотрудники с одинаковым количеством проектов получают одинаковый ранг.

26
New cards

Описание: Ранжируйте клиентов по общей сумме их покупок в каждой категории, не пропуская ранги при одинаковых суммах.

Таблица purchases:

client_id

category_id

purchase_amount

1

A

100

2

A

200

3

A

100

4

B

300

5

B

250

6

B

250

SELECT client_id, category_id, SUM(purchase_amount) AS total_amount,
       DENSE_RANK() OVER (PARTITION BY category_id ORDER BY SUM(purchase_amount) DESC) AS purchase_rank
FROM purchases
GROUP BY client_id, category_id;

Результат:

client_id

category_id

total_amount

purchase_rank

2

A

200

1

1

A

100

2

3

A

100

2

4

B

300

1

5

B

250

2

6

B

250

2

Объяснение: DENSE_RANK() ранжирует клиентов по общей сумме покупок в каждой категории, где одинаковые суммы покупок получают одинаковый ранг.

27
New cards

Описание: Разделите сотрудников на 4 группы (квартали) по их зарплате.

Таблица employees:

employee_id

salary

1

30000

2

50000

3

40000

4

70000

5

60000

6

35000

7

80000

8

45000

9

55000

SELECT employee_id, salary,
       NTILE(4) OVER (ORDER BY salary) AS salary_quartile
FROM employees;

Результат:

employee_id

salary

salary_quartile

1

30000

1

6

35000

1

3

40000

2

8

45000

2

9

55000

3

2

50000

3

5

60000

4

4

70000

4

7

80000

4

Объяснение: NTILE(4) делит сотрудников на 4 группы по зарплате. Сотрудники с наименьшей зарплатой попадают в первую группу, а с наибольшей — в последнюю.

28
New cards

Описание: Разделите студентов на 3 группы (трети) по их оценкам.

Таблица student_grades:

student_id

grade

1

85

2

92

3

88

4

75

5

90

6

82

7

95

8

78

9

87

SELECT student_id, grade,
       NTILE(3) OVER (ORDER BY grade DESC) AS grade_quartile
FROM student_grades;

Результат:

student_id

grade

grade_quartile

7

95

1

5

90

1

2

92

1

3

88

2

9

87

2

1

85

2

6

82

3

8

78

3

4

75

3

Объяснение: NTILE(3) делит студентов на 3 группы по оценкам. Студенты с высокими оценками попадают в первую группу, средние в вторую, и низкие в третью.

29
New cards

Описание: Разделите продукты на 5 групп по объему продаж.

Таблица products:

product_id

sales

1

2000

2

1500

3

2500

4

1000

5

3000

6

1800

7

1700

8

2200

9

1600

SELECT product_id, sales,
       NTILE(5) OVER (ORDER BY sales DESC) AS sales_quintile
FROM products;

Результат:

product_id

sales

sales_quintile

5

3000

1

3

2500

1

8

2200

1

9

1600

2

6

1800

2

7

1700

2

2

1500

3

1

2000

3

4

1000

5

Объяснение: NTILE(5) разделяет продукты на 5 групп по объему продаж. Продукты с наибольшими продажами попадают в первую группу, а с наименьшими — в последнюю.

30
New cards

Описание: Разделите проекты на 3 группы по их бюджету.

Таблица projects:

project_id

budget

1

50000

2

70000

3

30000

4

100000

5

60000

6

40000

7

80000

8

20000

9

90000

SELECT project_id, budget,
       NTILE(3) OVER (ORDER BY budget DESC) AS budget_quartile
FROM projects;

Результат:

project_id

budget

budget_quartile

4

100000

1

9

90000

1

7

80000

1

2

70000

2

5

60000

2

1

50000

2

6

40000

3

3

30000

3

8

20000

3

Объяснение: NTILE(3) делит проекты на 3 группы по бюджету. Проекты с наибольшим бюджетом попадают в первую группу, средние — во вторую, и с наименьшим — в третью.

31
New cards

Описание: Для каждого сотрудника покажите разницу между зарплатой в текущем месяце и предыдущем месяце.

Таблица salaries:

employee_id

month

salary

1

2024-01

3000

1

2024-02

3200

1

2024-03

3100

2

2024-01

2500

2

2024-02

2600

2

2024-03

2700

SELECT employee_id, month, salary,
       LAG(salary) OVER (PARTITION BY employee_id ORDER BY month) AS previous_salary,
       salary - LAG(salary) OVER (PARTITION BY employee_id ORDER BY month) AS salary_change
FROM salaries;

Результат:

employee_id

month

salary

previous_salary

salary_change

1

2024-01

3000

NULL

NULL

1

2024-02

3200

3000

200

1

2024-03

3100

3200

-100

2

2024-01

2500

NULL

NULL

2

2024-02

2600

2500

100

2

2024-03

2700

2600

100

Объяснение: LAG(salary) возвращает зарплату за предыдущий месяц для каждого сотрудника. Мы вычисляем разницу между текущей и предыдущей зарплатой, чтобы увидеть, как она изменяется.

32
New cards

Задача 2: Отслеживание изменения цен товаров

Описание: Для каждого товара покажите изменение цены по сравнению с предыдущим значением.

Таблица product_prices:

product_id

date

price

1

2024-01-01

100

1

2024-02-01

110

1

2024-03-01

105

2

2024-01-01

200

2

2024-02-01

210

2

2024-03-01

220

SELECT product_id, date, price,
       LAG(price) OVER (PARTITION BY product_id ORDER BY date) AS previous_price,
       price - LAG(price) OVER (PARTITION BY product_id ORDER BY date) AS price_change
FROM product_prices;

Результат:

product_id

date

price

previous_price

price_change

1

2024-01-01

100

NULL

NULL

1

2024-02-01

110

100

10

1

2024-03-01

105

110

-5

2

2024-01-01

200

NULL

NULL

2

2024-02-01

210

200

10

2

2024-03-01

220

210

10

Объяснение: LAG(price) позволяет увидеть изменение цены товара по сравнению с предыдущим значением. Мы вычисляем разницу между текущей и предыдущей ценой.

33
New cards

Описание: Для каждого заказа покажите предыдущий статус и дату, когда он был изменен.

Таблица order_statuses:

order_id

status

status_date

1

Shipped

2024-01-10

1

Delivered

2024-01-15

2

Pending

2024-01-12

2

Shipped

2024-01-18

SELECT order_id, status, status_date,
       LAG(status) OVER (PARTITION BY order_id ORDER BY status_date) AS previous_status,
       LAG(status_date) OVER (PARTITION BY order_id ORDER BY status_date) AS previous_status_date
FROM order_statuses;

Результат:

order_id

status

status_date

previous_status

previous_status_date

1

Shipped

2024-01-10

NULL

NULL

1

Delivered

2024-01-15

Shipped

2024-01-10

2

Pending

2024-01-12

NULL

NULL

2

Shipped

2024-01-18

Pending

2024-01-12

Объяснение: LAG(status) позволяет увидеть предыдущий статус и дату изменения статуса для каждого заказа.

34
New cards

Описание: Определите время ожидания между этапами для каждого проекта.

Таблица project_stages:

project_id

stage

start_date

1

Planning

2024-01-01

1

Execution

2024-02-01

1

Review

2024-03-01

2

Planning

2024-01-05

2

Execution

2024-02-10

2

Review

2024-03-15

SELECT project_id, stage, start_date,
       LAG(start_date) OVER (PARTITION BY project_id ORDER BY start_date) AS previous_start_date,
       start_date - LAG(start_date) OVER (PARTITION BY project_id ORDER BY start_date) AS wait_time
FROM project_stages;

Результат:

project_id

stage

start_date

previous_start_date

wait_time

1

Planning

2024-01-01

NULL

NULL

1

Execution

2024-02-01

2024-01-01

31 days

1

Review

2024-03-01

2024-02-01

28 days

2

Planning

2024-01-05

NULL

NULL

2

Execution

2024-02-10

2024-01-05

36 days

2

Review

2024-03-15

2024-02-10

34 days

Объяснение: LAG(start_date) позволяет узнать, когда начался предыдущий этап и вычислить время ожидания между этапами.

35
New cards

Описание: Вычислите изменение количества продаж по сравнению с предыдущим днем.

Таблица daily_sales:

date

sales

2024-01-01

100

2024-01-02

150

2024-01-03

120

2024-01-04

180

2024-01-05

160

SELECT date, sales,
       LAG(sales) OVER (ORDER BY date) AS previous_sales,
       sales - LAG(sales) OVER (ORDER BY date) AS sales_change
FROM daily_sales;

Результат:

date

sales

previous_sales

sales_change

2024-01-01

100

NULL

NULL

2024-01-02

150

100

50

2024-01-03

120

150

-30

2024-01-04

180

120

60

36
New cards

Описание: Определите разницу в количестве посещений для каждого пользователя по сравнению с предыдущим посещением.

Таблица user_visits:

user_id

visit_date

visit_count

1

2024-01-01

5

1

2024-01-05

8

1

2024-01-10

7

2

2024-01-02

4

2

2024-01-07

6

2

2024-01-15

5

SELECT user_id, visit_date, visit_count,
       LAG(visit_count) OVER (PARTITION BY user_id ORDER BY visit_date) AS previous_visit_count,
       visit_count - LAG(visit_count) OVER (PARTITION BY user_id ORDER BY visit_date) AS visit_change
FROM user_visits;

Результат:

user_id

visit_date

visit_count

previous_visit_count

visit_change

1

2024-01-01

5

NULL

NULL

1

2024-01-05

8

5

3

1

2024-01-10

7

8

-1

2

2024-01-02

4

NULL

NULL

2

2024-01-07

6

4

2

2

2024-01-15

5

6

-1

Объяснение: LAG(visit_count) позволяет увидеть количество посещений в предыдущий раз для каждого пользователя и вычислить разницу.

37
New cards

Описание: Для каждого региона рассчитайте разницу в объемах продаж между текущим и предыдущим месяцем.

Таблица monthly_sales:

region

month

sales

East

2024-01

1200

East

2024-02

1300

East

2024-03

1250

West

2024-01

1500

West

2024-02

1400

West

2024-03

1600

SELECT region, month, sales,
       LAG(sales) OVER (PARTITION BY region ORDER BY month) AS previous_sales,
       sales - LAG(sales) OVER (PARTITION BY region ORDER BY month) AS sales_change
FROM monthly_sales;

Результат:

region

month

sales

previous_sales

sales_change

East

2024-01

1200

NULL

NULL

East

2024-02

1300

1200

100

East

2024-03

1250

1300

-50

West

2024-01

1500

NULL

NULL

West

2024-02

1400

1500

-100

West

2024-03

1600

1400

200

Объяснение: LAG(sales) показывает продажи в предыдущем месяце для каждого региона, и мы вычисляем изменение в продажах.

38
New cards

Описание: Для каждого клиента покажите информацию о первом заказе.

Таблица customer_orders:

customer_id

order_date

order_amount

1

2024-01-10

150

1

2024-03-15

200

2

2024-02-01

300

2

2024-04-20

250

3

2024-01-25

120

SELECT customer_id, order_date, order_amount,
       FIRST_VALUE(order_date) OVER (PARTITION BY customer_id ORDER BY order_date) AS first_order_date,
       FIRST_VALUE(order_amount) OVER (PARTITION BY customer_id ORDER BY order_date) AS first_order_amount
FROM customer_orders;

Результат:

customer_id

order_date

order_amount

first_order_date

first_order_amount

1

2024-01-10

150

2024-01-10

150

1

2024-03-15

200

2024-01-10

150

2

2024-02-01

300

2024-02-01

300

2

2024-04-20

250

2024-02-01

300

3

2024-01-25

120

2024-01-25

120

Объяснение: FIRST_VALUE(order_date) и FIRST_VALUE(order_amount) возвращают дату и сумму первого заказа для каждого клиента.

39
New cards

Описание: Для каждого проекта покажите первый этап и его дату начала.

Таблица project_stages:

project_id

stage

start_date

1

Planning

2024-01-01

1

Execution

2024-02-01

1

Review

2024-03-01

2

Planning

2024-02-01

2

Execution

2024-03-01

2

Review

2024-04-01

SELECT project_id, stage, start_date,
       FIRST_VALUE(stage) OVER (PARTITION BY project_id ORDER BY start_date) AS first_stage,
       FIRST_VALUE(start_date) OVER (PARTITION BY project_id ORDER BY start_date) AS first_stage_start_date
FROM project_stages;

Результат:

project_id

stage

start_date

first_stage

first_stage_start_date

1

Planning

2024-01-01

Planning

2024-01-01

1

Execution

2024-02-01

Planning

2024-01-01

1

Review

2024-03-01

Planning

2024-01-01

2

Planning

2024-02-01

Planning

2024-02-01

2

Execution

2024-03-01

Planning

2024-02-01

2

Review

2024-04-01

Planning

2024-02-01

Объяснение: FIRST_VALUE(stage) и FIRST_VALUE(start_date) возвращают первый этап проекта и дату его начала.

40
New cards

Описание: Определите первый доход, полученный каждым продуктом в течение года.

Таблица product_revenue:

product_id

revenue_date

revenue_amount

1

2024-01-10

500

1

2024-03-15

600

2

2024-02-01

300

2

2024-05-20

400

3

2024-01-25

200

SELECT product_id, revenue_date, revenue_amount,
       FIRST_VALUE(revenue_date) OVER (PARTITION BY product_id ORDER BY revenue_date) AS first_revenue_date,
       FIRST_VALUE(revenue_amount) OVER (PARTITION BY product_id ORDER BY revenue_date) AS first_revenue_amount
FROM product_revenue;

Результат:

product_id

revenue_date

revenue_amount

first_revenue_date

first_revenue_amount

1

2024-01-10

500

2024-01-10

500

1

2024-03-15

600

2024-01-10

500

2

2024-02-01

300

2024-02-01

300

2

2024-05-20

400

2024-02-01

300

3

2024-01-25

200

2024-01-25

200

Объяснение: FIRST_VALUE(revenue_date) и FIRST_VALUE(revenue_amount) возвращают дату и сумму первого дохода для каждого продукта.

41
New cards

Описание: Определите процентиль для каждой оценки студентов по предмету. Это поможет понять, как оценки распределены в классе.

Таблица student_scores:

student_id

subject

score

1

Math

85

2

Math

90

3

Math

78

4

Math

92

5

Math

88

SELECT student_id, subject, score,
       PERCENT_RANK() OVER (PARTITION BY subject ORDER BY score) AS percentile_rank
FROM student_scores;

Результат:

student_id

subject

score

percentile_rank

3

Math

78

0.00

1

Math

85

0.25

5

Math

88

0.50

2

Math

90

0.75

4

Math

92

1.00

Объяснение: PERCENT_RANK() вычисляет процентиль для каждой оценки в рамках предмета. Например, оценка 78 находится на 0-й процентиле, а оценка 92 на 100-й процентиле.

42
New cards

Описание: Определите процентиль для продаж сотрудников в конкретном месяце, чтобы понять их относительное положение.

Таблица employee_sales:

employee_id

sales_month

sales_amount

1

2024-01

5000

2

2024-01

6000

3

2024-01

5500

4

2024-01

7000

5

2024-01

6500

SELECT employee_id, sales_month, sales_amount,
       PERCENT_RANK() OVER (PARTITION BY sales_month ORDER BY sales_amount) AS percentile_rank
FROM employee_sales;

Результат:

employee_id

sales_month

sales_amount

percentile_rank

1

2024-01

5000

0.00

3

2024-01

5500

0.25

5

2024-01

6500

0.50

2

2024-01

6000

0.75

4

2024-01

7000

1.00

Объяснение: PERCENT_RANK() вычисляет процентиль для каждой продажи в рамках месяца. Это помогает понять, как продажи сотрудников распределены.

43
New cards

Описание: Определите процентиль для производительности сотрудников на основе числа выполненных задач.

Таблица employee_performance:

employee_id

tasks_completed

1

10

2

15

3

12

4

20

5

18

SELECT employee_id, tasks_completed,
       PERCENT_RANK() OVER (ORDER BY tasks_completed) AS percentile_rank
FROM employee_performance;

Результат:

employee_id

tasks_completed

percentile_rank

1

10

0.00

3

12

0.25

2

15

0.50

5

18

0.75

4

20

1.00

Объяснение: PERCENT_RANK() вычисляет процентиль для числа выполненных задач, позволяя сравнить производительность сотрудников.

44
New cards

Найти сотрудников, чья зарплата выше средней зарплаты в компании

Таблица employees:

employee_id

name

salary

1

Alice

50000

2

Bob

60000

3

Charlie

55000

4

David

70000

5

Eve

65000

SELECT name, salary
FROM employees
WHERE salary > (SELECT AVG(salary) FROM employees);

Объяснение: Скалярный подзапрос (SELECT AVG(salary) FROM employees) вычисляет среднюю зарплату по всей таблице, а основной запрос возвращает имена сотрудников с зарплатой выше этой средней.

Результат:

name

salary

Bob

60000

Charlie

55000

David

70000

Eve

65000

45
New cards

Найти сотрудников, работающих в самой большой команде

Таблица teams:

team_id

team_name

1

Development

2

Marketing

3

HR

Таблица employees:

employee_id

name

team_id

1

Alice

1

2

Bob

1

3

Charlie

2

4

David

1

5

Eve

3

SELECT name, team_id
FROM employees
WHERE team_id = (SELECT team_id
                 FROM employees
                 GROUP BY team_id
                 ORDER BY COUNT(*) DESC
                 LIMIT 1);

Объяснение: Внутренний подзапрос определяет team_id самой крупной команды (с максимальным числом сотрудников). Основной запрос возвращает сотрудников, работающих в этой команде.

Результат:

name

team_id

Alice

1

Bob

1

David

1

46
New cards

Описание задачи: У вас есть две таблицы: Orders и Customers. Вам нужно найти список всех заказов с именами клиентов, которые их разместили.

Таблицы:

Таблица Orders:

order_id

customer_id

order_date

1

101

2024-01-01

2

102

2024-01-02

3

103

2024-01-03

4

101

2024-01-04

Таблица Customers:

customer_id

customer_name

101

Иван Иванов

102

Мария Смирнова

103

Алексей Кузнецов

SELECT orders.order_id, customers.customer_name, orders.order_date
FROM orders
INNER JOIN customers ON orders.customer_id = customers.customer_id;

Результат:

order_id

customer_name

order_date

1

Иван Иванов

2024-01-01

2

Мария Смирнова

2024-01-02

3

Алексей Кузнецов

2024-01-03

4

Иван Иванов

2024-01-04

Объяснение: INNER JOIN объединяет таблицы Orders и Customers по полю customer_id. В результате получается таблица, содержащая информацию о заказах вместе с именами клиентов, которые их разместили.

47
New cards

Описание задачи: У вас есть две таблицы: Employees и Departments. Вам нужно найти список всех сотрудников вместе с их названиями отделов.

Таблицы:

Таблица Employees:

employee_id

name

department_id

1

Алексей Петров

10

2

Ольга Иванова

20

3

Дмитрий Смирнов

10

4

Мария Сергеева

30

Таблица Departments:

department_id

department_name

10

IT

20

Бухгалтерия

30

Маркетинг

SELECT Employees.name, Departments.department_name
FROM Employees
INNER JOIN Departments ON Employees.department_id = Departments.department_id;

Результат:

name

department_name

Алексей Петров

IT

Ольга Иванова

Бухгалтерия

Дмитрий Смирнов

IT

Мария Сергеева

Маркетинг

Объяснение: INNER JOIN соединяет таблицы Employees и Departments по полю department_id, что позволяет получить информацию о сотрудниках и их отделах.

48
New cards

Описание задачи: У вас есть две таблицы: Books и Authors. Вам нужно найти список всех книг с именами их авторов.

Таблицы:

Таблица Books:

book_id

book_title

author_id

1

Война и мир

1001

2

Преступление и наказание

1002

3

Идиот

1002

4

Анна Каренина

1001

Таблица Authors:

author_id

author_name

1001

Лев Толстой

1002

Федор Достоевский

SELECT Books.book_title, Authors.author_name
FROM Books
INNER JOIN Authors ON Books.author_id = Authors.author_id;

Результат:

book_title

author_name

Война и мир

Лев Толстой

Преступление и наказание

Федор Достоевский

Идиот

Федор Достоевский

Анна Каренина

Лев Толстой

Объяснение: INNER JOIN объединяет таблицы Books и Authors по полю author_id, что позволяет получить информацию о книгах и их авторах.

49
New cards

Описание задачи: У вас есть две таблицы: Employees и Departments. Вам нужно получить список всех сотрудников вместе с их отделами, включая сотрудников, которые еще не назначены в отдел.

Таблицы:

Таблица Employees:

employee_id

name

department_id

1

Алексей Петров

10

2

Ольга Иванова

NULL

3

Дмитрий Смирнов

20

4

Мария Сергеева

30

Таблица Departments:

department_id

department_name

10

IT

20

Бухгалтерия

30

Маркетинг

SELECT Employees.name, Departments.department_name
FROM Employees
LEFT JOIN Departments ON Employees.department_id = Departments.department_id;

Результат:

employee_name

department_name

Алексей Петров

IT

Ольга Иванова

NULL

Дмитрий Смирнов

Бухгалтерия

Мария Сергеева

Маркетинг

Объяснение: LEFT JOIN возвращает все строки из таблицы Employees, даже если у них нет соответствующих записей в таблице Departments. Для сотрудников без отдела (где department_id равно NULL), поле department_name также будет NULL.

50
New cards

Описание задачи: У вас есть две таблицы: Orders и Customers. Вам нужно найти список всех заказов, включая те, которые были сделаны анонимными клиентами (без регистрации в базе данных).

Таблицы:

Таблица Orders:

order_id

customer_id

order_date

1

101

2024-01-01

2

NULL

2024-01-02

3

102

2024-01-03

4

103

2024-01-04

Таблица Customers:

customer_id

customer_name

101

Иван Иванов

102

Мария Смирнова

103

Алексей Кузнецов

SELECT Orders.order_id, Customers.customer_name, Orders.order_date
FROM Orders
LEFT JOIN Customers ON Orders.customer_id = Customers.customer_id;

Результат:

order_id

customer_name

order_date

1

Иван Иванов

2024-01-01

2

NULL

2024-01-02

3

Мария Смирнова

2024-01-03

4

Алексей Кузнецов

2024-01-04

Объяснение: LEFT JOIN позволяет вернуть все заказы, даже если для них нет информации о клиенте (где customer_id равно NULL). В таких случаях поле customer_name будет NULL.

51
New cards

Описание задачи: У вас есть две таблицы: Students и Courses. Вам нужно получить список всех студентов и курсов, на которые они записаны, включая тех студентов, которые еще не зарегистрировались ни на один курс.

Таблицы:

Таблица Students:

student_id

student_name

1

Анна Кузнецова

2

Борис Иванов

3

Вера Смирнова

Таблица Courses:

course_id

course_name

student_id

1

Математика

1

2

История

1

3

Литература

NULL

SELECT Students.student_name, Courses.course_name
FROM Students
LEFT JOIN Courses ON Students.student_id = Courses.student_id;

Результат:

student_name

course_name

Анна Кузнецова

Математика

Анна Кузнецова

История

Борис Иванов

NULL

Вера Смирнова

NULL

Объяснение: LEFT JOIN возвращает всех студентов, даже если они не зарегистрированы ни на один курс (где student_id равно NULL в таблице Courses). В таких случаях поле course_name будет NULL.

52
New cards

Описание задачи: У вас есть две таблицы: Books и Authors. Вам нужно найти список всех книг, включая те, у которых автор не указан в базе данных.

Таблицы:

Таблица Books:

book_id

book_title

author_id

1

Война и мир

1001

2

Преступление и наказание

1002

3

Идиот

NULL

4

Анна Каренина

1001

Таблица Authors:

author_id

author_name

1001

Лев Толстой

1002

Федор Достоевский

SELECT Books.book_title, Authors.author_name
FROM Books
LEFT JOIN Authors ON Books.author_id = Authors.author_id;

Результат:

book_title

author_name

Война и мир

Лев Толстой

Преступление и наказание

Федор Достоевский

Идиот

NULL

Анна Каренина

Лев Толстой

Объяснение: LEFT JOIN возвращает все книги, даже если для них нет информации о авторе (где author_id равно NULL). В таких случаях поле author_name будет NULL.

53
New cards

Задача 1: Список всех отделов и сотрудников, работающих в них

Описание задачи: У вас есть две таблицы: Employees и Departments. Вам нужно получить список всех отделов и сотрудников, работающих в них, включая отделы, в которых пока нет сотрудников.

Таблицы:

Таблица Employees:

employee_id

employee_name

department_id

1

Алексей Петров

10

2

Ольга Иванова

20

3

Дмитрий Смирнов

10

Таблица Departments:

department_id

department_name

10

IT

20

Бухгалтерия

30

Маркетинг

SELECT Employees.employee_name, Departments.department_name
FROM Employees
RIGHT JOIN Departments ON Employees.department_id = Departments.department_id;

Результат:

employee_name

department_name

Алексей Петров

IT

Дмитрий Смирнов

IT

Ольга Иванова

Бухгалтерия

NULL

Маркетинг

Объяснение: RIGHT JOIN соединяет таблицы Employees и Departments по полю department_id, при этом выбираются все записи из таблицы Departments, даже если в соответствующем отделе нет сотрудников. В случае отсутствия сотрудников для конкретного отдела, в столбце employee_name будет NULL.

54
New cards

Описание задачи: У вас есть две таблицы: Orders и Customers. Вам нужно получить список всех клиентов и их заказов, включая клиентов, которые пока не сделали заказ.

Таблицы:

Таблица Orders:

order_id

customer_id

order_date

1

101

2024-01-01

2

102

2024-01-02

3

101

2024-01-03

Таблица Customers:

customer_id

customer_name

101

Иван Иванов

102

Мария Смирнова

103

Алексей Кузнецов

SELECT Customers.customer_name, Orders.order_id, Orders.order_date
FROM Orders
RIGHT JOIN Customers ON Orders.customer_id = Customers.customer_id;

Результат:

customer_name

order_id

order_date

Иван Иванов

1

2024-01-01

Иван Иванов

3

2024-01-03

Мария Смирнова

2

2024-01-02

Алексей Кузнецов

NULL

NULL

Объяснение: RIGHT JOIN соединяет таблицы Orders и Customers по полю customer_id, при этом выбираются все записи из таблицы Customers, даже если у клиента еще нет заказов. Если клиент не сделал заказ, столбцы order_id и order_date будут содержать NULL.

55
New cards

Описание задачи: У вас есть две таблицы: Students и Courses. Вам нужно получить список всех курсов и студентов, записанных на них, включая курсы, на которые никто еще не записался.

Таблицы:

Таблица Students:

student_id

student_name

1

Анна Сергеева

2

Иван Петров

Таблица Courses:

course_id

course_name

student_id

101

Математика

1

102

Литература

2

103

Физика

NULL

SELECT Courses.course_name, Students.student_name
FROM Students
RIGHT JOIN Courses ON Students.student_id = Courses.student_id;

Результат:

course_name

student_name

Математика

Анна Сергеева

Литература

Иван Петров

Физика

NULL

Объяснение: RIGHT JOIN соединяет таблицы Students и Courses по полю student_id, при этом выбираются все записи из таблицы Courses, даже если на курс никто еще не записался. В этом случае, если на курсе нет студентов, столбец student_name будет содержать NULL.

56
New cards

Описание задачи: У вас есть таблица Employees, которая содержит информацию о сотрудниках и их руководителях. Вам нужно найти всех сотрудников, которые подчиняются одному и тому же руководителю.

Таблица Employees:

employee_id

employee_name

manager_id

1

Иван Иванов

3

2

Мария Смирнова

3

3

Алексей Петров

NULL

4

Дмитрий Кузнецов

3

5

Ольга Сергеева

4

SELECT e1.employee_name AS employee, e2.employee_name AS manager
FROM Employees e1
JOIN Employees e2 ON e1.manager_id = e2.employee_id;

Результат:

employee

manager

Иван Иванов

Алексей Петров

Мария Смирнова

Алексей Петров

Дмитрий Кузнецов

Алексей Петров

Ольга Сергеева

Дмитрий Кузнецов

Объяснение: SELF JOIN используется для того, чтобы соединить таблицу Employees саму с собой. Мы сопоставляем сотрудников (e1) с их руководителями (e2) через поле manager_id. В результате получается таблица с именами сотрудников и их менеджеров.

57
New cards

Описание задачи: У вас есть таблица Employees, которая содержит информацию о сотрудниках и их отделах. Вам нужно найти все пары сотрудников, работающих в одном и том же отделе.

Таблица Employees:

employee_id

name

department_id

1

Иван Иванов

10

2

Мария Смирнова

20

3

Алексей Петров

10

4

Дмитрий Кузнецов

30

5

Ольга Сергеева

20

SELECT e1.name AS employee1, e2.name AS employee2
FROM Employees e1
JOIN Employees e2 ON e1.department_id = e2.department_id
WHERE e1.employee_id < e2.employee_id

Результат:

employee1

employee2

Иван Иванов

Алексей Петров

Мария Смирнова

Ольга Сергеева

Объяснение: SELF JOIN используется для нахождения пар сотрудников, работающих в одном отделе. Условие WHERE e1.employee_id < e2.employee_id предотвращает дублирование и исключает пары сотрудник-сам-собой. В результате вы получаете список пар сотрудников, работающих в одном и том же отделе.

58
New cards

Описание задачи: У вас есть таблица Employees, которая содержит информацию о сотрудниках, их отделах и зарплатах. Вам нужно найти сотрудников, которые зарабатывают больше всех других сотрудников в их отделе.

Таблица Employees:

employee_id

name

department_id

salary

1

Иван Иванов

10

50000

2

Мария Смирнова

20

60000

3

Алексей Петров

10

55000

4

Дмитрий Кузнецов

30

70000

5

Ольга Сергеева

20

60000

SELECT e1.name, e1.salary
FROM Employees e1
LEFT JOIN Employees e2 ON e1.department_id = e2.department_id AND e1.salary < e2.salary
WHERE e2.employee_id IS NULL

Результат:

employee_name

salary

Алексей Петров

55000

Дмитрий Кузнецов

70000

Объяснение: Здесь используется SELF JOIN для сравнения зарплат сотрудников в одном отделе. Если у сотрудника нет коллег в его отделе, которые зарабатывают больше (проверка WHERE e2.employee_id IS NULL), то этот сотрудник считается самым высокооплачиваемым в своем отделе.

59
New cards

Найти количество сотрудников в каждом департаменте

Таблица employees:

employee_id

name

department

salary

1

Alice

Sales

50000

2

Bob

Sales

55000

3

Charlie

HR

60000

4

David

HR

62000

5

Eve

IT

70000

WITH department_counts AS (
    SELECT department, COUNT(*) AS employee_count
    FROM employees
    GROUP BY department
)
SELECT department, employee_count
FROM department_counts;

Результат:

department

employee_count

Sales

2

HR

2

IT

1

Объяснение: CTE department_counts считает количество сотрудников в каждом департаменте, группируя данные по колонке department. Основной запрос просто выбирает данные из CTE.

60
New cards

Найти сотрудников с зарплатой выше среднего

Таблица employees:

employee_id

name

department

salary

1

Alice

Sales

50000

2

Bob

Sales

55000

3

Charlie

HR

60000

4

David

HR

62000

5

Eve

IT

70000

WITH avg_salary AS (
    SELECT AVG(salary) AS overall_avg_salary
    FROM employees
)
SELECT name, department, salary
FROM employees
WHERE salary > (SELECT overall_avg_salary FROM avg_salary);

Объяснение: CTE avg_salary вычисляет среднюю зарплату всех сотрудников. Основной запрос выбирает сотрудников, чья зарплата выше этой средней.

Результат:

name

department

salary

Charlie

HR

60000

David

HR

62000

Eve

IT

70000

61
New cards

Найти самую низкую зарплату в каждом департаменте

Таблица employees:

employee_id

name

department

salary

1

Alice

Sales

50000

2

Bob

Sales

55000

3

Charlie

HR

60000

4

David

HR

62000

5

Eve

IT

70000

WITH min_salaries AS (
    SELECT department, MIN(salary) AS min_salary
    FROM employees
    GROUP BY department
)
SELECT department, min_salary
FROM min_salaries;

Объяснение: CTE min_salaries определяет минимальную зарплату в каждом департаменте, группируя данные по колонке department.

Результат:

department

min_salary

Sales

50000

HR

60000

IT

70000

62
New cards

Найти сотрудников, которые зарабатывают больше среднего по своему департаменту

Таблица employees:

employee_id

name

department

salary

1

Alice

Sales

50000

2

Bob

Sales

55000

3

Charlie

HR

60000

4

David

HR

62000

5

Eve

IT

70000

WITH department_avg_salary AS (
    SELECT department, AVG(salary) AS avg_salary
    FROM employees
    GROUP BY department
)
SELECT e.name, e.department, e.salary
FROM employees e
JOIN department_avg_salary das
ON e.department = das.department
WHERE e.salary > das.avg_salary;

Объяснение: CTE department_avg_salary вычисляет среднюю зарплату по каждому департаменту. Основной запрос выбирает сотрудников, чья зарплата выше средней по их департаменту.

Результат:

name

department

salary

Bob

Sales

55000

David

HR

62000

63
New cards

Подсчитать общее количество сотрудников и общую сумму зарплат

Таблица employees:

employee_id

name

department

salary

1

Alice

Sales

50000

2

Bob

Sales

55000

3

Charlie

HR

60000

4

David

HR

62000

5

Eve

IT

70000

WITH totals AS (
    SELECT COUNT(*) AS total_employees, SUM(salary) AS total_salary
    FROM employees
)
SELECT total_employees, total_salary
FROM totals;

Объяснение: CTE totals вычисляет общее количество сотрудников и сумму их зарплат. Основной запрос просто выбирает эти значения из CTE.

Результат:

total_employees

total_salary

5

297000

64
New cards

Оптимизируйте SQL запрос и объясните своё решение

SELECT e.employee_id, e.name
FROM employees e
WHERE e.salary > (SELECT AVG(salary) FROM employees WHERE department_id = e.department_id);

WITH dept_avg_salary AS (
    SELECT department_id, AVG(salary) AS avg_salary
    FROM employees
    GROUP BY department_id
)
SELECT e.employee_id, e.name
FROM employees e
JOIN dept_avg_salary das ON e.department_id = das.department_id
WHERE e.salary > das.avg_salary;

Обоснование:

  • Использование CTE: CTE позволяет один раз вычислить среднюю зарплату по департаменту, а затем использовать результат для фильтрации сотрудников. Это устраняет необходимость повторного выполнения подзапроса для каждой строки в таблице employees.

  • JOIN вместо подзапроса: В большинстве случаев JOIN более эффективен, чем подзапрос, особенно если используется CTE или предварительно агрегированные данные.

Потенциальное ускорение: Ожидаемое ускорение в 2-4 раза.

65
New cards

Оптимизируйте SQL запрос и объясните своё решение

SELECT c.customer_id, c.customer_name, SUM(o.total_amount) AS total_spent
FROM customers c
JOIN orders o ON c.customer_id = o.customer_id
WHERE o.order_date >= '2023-01-01'
GROUP BY c.customer_id, c.customer_name;

SELECT c.customer_id, c.customer_name, total_spent
FROM customers c
JOIN (
    SELECT customer_id, SUM(total_amount) AS total_spent
    FROM orders
    WHERE order_date >= '2023-01-01'
    GROUP BY customer_id
) o_sum ON c.customer_id = o_sum.customer_id;

Обоснование:

  • Предварительная агрегация: Агрегация данных по заказам выполняется до выполнения JOIN. Это позволяет уменьшить объем данных, с которыми работает основной запрос, что снижает нагрузку и ускоряет выполнение.

Потенциальное ускорение: Оптимизация может ускорить запрос в 1.5-2 раза, особенно если таблица orders содержит большое количество данных.

66
New cards

delete

Оптимизируйте SQL запрос и объясните своё решение

SELECT order_id, customer_id, total_amount
FROM orders
WHERE total_amount > 100 AND order_date > '2023-01-01' AND status = 'completed';

SELECT order_id, customer_id, total_amount
FROM orders
WHERE status = 'completed' AND order_date > '2023-01-01' AND total_amount > 100;

Обоснование:

  • Расположение условий: В PostgreSQL порядок условий в WHERE может влиять на производительность, особенно если одни условия более селективны, чем другие. Помещение наиболее селективных условий в начало может уменьшить количество строк, которые проходят через последующие фильтры.

Потенциальное ускорение: В зависимости от данных, улучшение может быть незначительным, но иногда может ускорить запрос в 1.5-2 раза.

67
New cards
SELECT order_id, product_id
FROM orders
WHERE product_id = ANY (ARRAY[1, 2, 3]);

Оптимизируйте SQL запрос и объясните своё решение

SELECT order_id, product_id
FROM orders
WHERE product_id IN (1, 2, 3);

Обоснование:

  • Замена ANY на IN: В PostgreSQL использование IN может быть более эффективным, чем ANY при работе с небольшими наборами данных. Это связано с тем, что IN легче оптимизируется и исполняется быстрее.

Потенциальное ускорение: В зависимости от количества данных, улучшение может быть в 1.5-2 раза.

68
New cards

Ситуация: У вас есть таблица users, которая содержит миллионы записей с информацией о пользователях. Часто требуется быстро находить пользователя по его уникальному идентификатору (user_id), который является нечисловым полем, например, UUID или строка.

Задание: Создайте HASH индекс на поле user_id, чтобы ускорить выполнение запроса, и объясните, почему в данном случае использование HASH индекса предпочтительно.

CREATE INDEX idx_users_user_id_hash ON users USING HASH (user_id);

Обоснование:

  • Когда использовать HASH индекс: HASH индексы идеально подходят для точных соответствий (=) по значению, особенно если это частая операция. Они обеспечивают быстрый доступ к данным при сравнении на равенство.

  • Преимущество HASH индекса: В отличие от индексов типа BTREE, которые эффективны для диапазонных запросов, HASH индексы могут быть быстрее при работе с точными значениями, так как они используют хэш-функцию для быстрого поиска соответствия.

69
New cards

Ситуация: У вас есть таблица locations, которая содержит географические координаты (долгота и широта) местоположений, используя тип данных point. Вам нужно часто находить все точки, находящиеся в определенном радиусе от заданной точки.

Задание: Создайте GiST индекс на поле с координатами и объясните, почему GiST индекс подходит для этой задачи.

CREATE INDEX idx_locations_point_gist ON locations USING GiST (point(longitude, latitude));

Обоснование:

  • Когда использовать GiST индекс: GiST индексы отлично подходят для географических данных, особенно для операций, связанных с поиском в пределах определенной области (например, точки в круге).

  • Эффективность: GiST индекс может существенно ускорить выполнение пространственных запросов, таких как поиск точек внутри окружности, прямоугольника или другой формы.