У меня есть таблица с именем Projects, которая имеет следующие отношения:
имеет много вкладов
имеет много платежей
В моем наборе результатов мне нужны следующие совокупные значения:
- Количество уникальных участников (DonorID в таблице взносов)
- Всего внесено (Сумма суммы в таблице взносов)
- Всего оплачено (Сумма платежаСумма на платёжной таблице)
Поскольку существует так много агрегатных функций и множественных объединений, становится грязно, поэтому используйте стандартные агрегатные функции в предложении GROUP BY. Мне также нужна возможность сортировать и фильтровать эти поля. Итак, я предложил два варианта:
Использование подзапросов:
SELECT Project.ID AS PROJECT_ID,
(SELECT SUM(PaymentAmount) FROM Payment WHERE ProjectID = PROJECT_ID) AS TotalPaidBack,
(SELECT COUNT(DISTINCT DonorID) FROM Contribution WHERE RecipientID = PROJECT_ID) AS ContributorCount,
(SELECT SUM(Amount) FROM Contribution WHERE RecipientID = PROJECT_ID) AS TotalReceived
FROM Project;
Использование временной таблицы:
DROP TABLE IF EXISTS Project_Temp;
CREATE TEMPORARY TABLE Project_Temp (project_id INT NOT NULL, total_payments INT, total_donors INT, total_received INT, PRIMARY KEY(project_id)) ENGINE=MEMORY;
INSERT INTO Project_Temp (project_id,total_payments)
SELECT `Project`.ID, IFNULL(SUM(PaymentAmount),0) FROM `Project` LEFT JOIN `Payment` ON ProjectID = `Project`.ID GROUP BY 1;
INSERT INTO Project_Temp (project_id,total_donors,total_received)
SELECT `Project`.ID, IFNULL(COUNT(DISTINCT DonorID),0), IFNULL(SUM(Amount),0) FROM `Project` LEFT JOIN `Contribution` ON RecipientID = `Project`.ID GROUP BY 1
ON DUPLICATE KEY UPDATE total_donors = VALUES(total_donors), total_received = VALUES(total_received);
SELECT * FROM Project_Temp;
Тесты для обоих довольно сопоставимы, в диапазоне 0,7 - 0,8 секунд с 1000 строк. Но я действительно обеспокоен масштабируемостью, и я не хочу перестраивать все по мере роста моих таблиц. Какой лучший подход?