Какие запросы базе данных писал?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Мой опыт работы с запросами к базам данных
За мою карьеру я писал огромное количество SQL-запросов различной сложности для разных СУБД, но преимущественно для Microsoft SQL Server и PostgreSQL, поскольку они наиболее распространены в .NET экосистеме. Вот основные категории запросов, с которыми я работал:
1. Базовые CRUD-операции
Это основа любого backend-приложения. Я писал все виды запросов для манипуляции данными:
-- SELECT с фильтрацией, сортировкой и пагинацией
SELECT Id, Name, Email, CreatedAt
FROM Users
WHERE IsActive = 1
ORDER BY CreatedAt DESC
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;
-- INSERT с возвратом сгенерированного ID
INSERT INTO Products (Name, Price, CategoryId)
VALUES ('New Product', 99.99, 5)
RETURNING Id;
-- UPDATE с джойнами
UPDATE Orders o
SET Status = 'Completed'
FROM Customers c
WHERE o.CustomerId = c.Id
AND c.Country = 'USA'
AND o.OrderDate < '2023-01-01';
-- DELETE с каскадными ограничениями
DELETE FROM ShoppingCarts
WHERE LastActivityDate < DATEADD(month, -6, GETDATE());
2. Сложные JOIN-запросы
Работа с реляционными данными требует мастерства в объединениях таблиц:
-- Множественные INNER и LEFT JOIN
SELECT
o.OrderId,
o.OrderDate,
c.CustomerName,
e.EmployeeName,
SUM(od.Quantity * p.UnitPrice) as TotalAmount
FROM Orders o
INNER JOIN Customers c ON o.CustomerId = c.CustomerId
LEFT JOIN Employees e ON o.EmployeeId = e.EmployeeId
INNER JOIN OrderDetails od ON o.OrderId = od.OrderId
INNER JOIN Products p ON od.ProductId = p.ProductId
GROUP BY o.OrderId, o.OrderDate, c.CustomerName, e.EmployeeName
HAVING SUM(od.Quantity * p.UnitPrice) > 1000;
3. Агрегирующие запросы и аналитика
Для отчетов и дашбордов часто использовал оконные функции:
-- Оконные функции для аналитики
SELECT
CustomerId,
OrderDate,
TotalAmount,
SUM(TotalAmount) OVER(PARTITION BY CustomerId ORDER BY OrderDate) as RunningTotal,
AVG(TotalAmount) OVER(PARTITION BY CustomerId) as CustomerAverage,
ROW_NUMBER() OVER(PARTITION BY CustomerId ORDER BY OrderDate DESC) as RecentOrderIndex
FROM Orders;
4. Оптимизированные запросы
Важной частью работы была оптимизация производительности:
-- Использование CTE для сложных иерархических запросов
WITH RecursiveCTE AS (
-- Якорная часть
SELECT EmployeeId, ManagerId, 1 as Level
FROM Employees
WHERE ManagerId IS NULL
UNION ALL
-- Рекурсивная часть
SELECT e.EmployeeId, e.ManagerId, r.Level + 1
FROM Employees e
INNER JOIN RecursiveCTE r ON e.ManagerId = r.EmployeeId
)
SELECT * FROM RecursiveCTE;
-- Оптимизация с временными таблицами для сложных вычислений
CREATE TABLE #TempSalesData (
ProductId INT,
TotalSales DECIMAL(18,2),
SalesCount INT
);
INSERT INTO #TempSalesData
SELECT ProductId, SUM(Amount), COUNT(*)
FROM Sales
WHERE SaleDate BETWEEN @StartDate AND @EndDate
GROUP BY ProductId;
5. Транзакционные запросы
Для обеспечения ACID-свойств и целостности данных:
BEGIN TRANSACTION;
BEGIN TRY
-- Резервируем товар
UPDATE Inventory
SET Quantity = Quantity - @OrderedQuantity
WHERE ProductId = @ProductId AND Quantity >= @OrderedQuantity;
-- Создаем заказ
INSERT INTO Orders (CustomerId, ProductId, Quantity, OrderDate)
VALUES (@CustomerId, @ProductId, @OrderedQuantity, GETDATE());
-- Фиксируем изменения
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
THROW;
END CATCH;
6. Запросы для миграций и обслуживания
Часто писал DDL-запросы для изменения структуры БД:
-- Создание индексов для оптимизации
CREATE NONCLUSTERED INDEX IX_Orders_CustomerId_OrderDate
ON Orders(CustomerId, OrderDate DESC)
INCLUDE (TotalAmount, Status);
-- Партиционирование больших таблиц
CREATE PARTITION FUNCTION OrderDateRangePF (DATE)
AS RANGE RIGHT FOR VALUES (
'2022-01-01', '2023-01-01', '2024-01-01'
);
7. Интеграция с Entity Framework Core
В .NET-проектах активно использовал LINQ to SQL и Entity Framework Core:
// Сложные запросы через LINQ
var result = await context.Orders
.Where(o => o.OrderDate >= startDate && o.OrderDate <= endDate)
.GroupBy(o => new { o.CustomerId, o.OrderDate.Year, o.OrderDate.Month })
.Select(g => new
{
g.Key.CustomerId,
g.Key.Year,
g.Key.Month,
TotalAmount = g.Sum(o => o.TotalAmount),
OrderCount = g.Count()
})
.OrderByDescending(x => x.TotalAmount)
.Take(100)
.ToListAsync();
// Raw SQL через EF Core при сложных запросах
var reports = await context.SalesReports
.FromSqlRaw(@"EXEC GenerateSalesReport @StartDate, @EndDate, @RegionId",
parameters)
.ToListAsync();
Основные принципы, которых я придерживаюсь:
- Безопасность: Всегда использую параметризованные запросы для предотвращения SQL-инъекций
- Производительность: Анализирую execution plan, добавляю индексы, избегаю N+1 проблем
- Читаемость: Форматирую сложные запросы, добавляю комментарии
- Масштабируемость: Учитываю блокировки и изоляцию транзакций
- Поддержка: Пишу идемпотентные миграционные скрипты
В зависимости от проекта, также работал с хранимыми процедурами, триггерами, представлениями, функциями и материализованными представлениями. Для NoSQL баз данных (в основном MongoDB и Redis) использовал соответствующие query language и паттерны доступа к данным.