У меня есть 3 таблицы, категория, человеческий ресурс и план управления персоналом.
Я хочу рассчитать сумму Группировать по категориям
Я создал этот SQL-запрос:
select
CostCategory.CostCategory, sum(isnull(HRPplan.Amount, 0))
from
CostCategory
left join
HRPplan on HRPplan.Month between 1 and 3
and HRPplan.Year = 2019
and HRPplan.IDRPH in (select HumanResource.IDRPH
from HumanResource
where HumanResource.IDCostCategory = CostCategory.IDCostegory)
group by
CostCategory.CostCategory
и он возвращает результат, но у меня есть еще 2 таблицы, точно похожие на Human Resource & HPlan, чтобы использовать их для расчета суммы, поэтому, если я использую тот же код, упомянутый выше, производительность запроса не очень хорошая. И я не знаю, как использовать функцию/процедуру в SQL, так как год и месяц будут вставлены в качестве параметра.
для повышения производительности вы можете избежать предложения in
select CostCategory.CostCategory, sum(isnull(HRPplan.Amount,0))
from CostCategory
left join HRPplan on HRPplan.Month between 1 and 3 and HRPplan.Year = 2019
LEFT JOIN HumanResource ON HumanResource.IDCostCategory = CostCategory.IDCostegory
and umanResource.IDRPH = HRPplan.IDRPH
group by CostCategory.CostCategory
Я не думаю, что этот запрос даст то, о чем просят. Порядок соединения должен быть изменен. Вы можете взглянуть на 2 решения, которые я предоставил ниже, и дайте мне знать.
Наличие DDL и образца данных DML в вопросах упрощает поиск быстрого решения. Кроме того, столбцы, используемые в вашем запросе, не полностью совпадают с предоставленным вами снимком экрана, поэтому я предлагаю эти подходы на основе предоставленного снимка экрана.
Подготовленный DDL и тестовые данные:
DROP TABLE IF EXISTS CostCategory;
GO
CREATE TABLE CostCategory
(
IDCostCategory INT
,CostCategory VARCHAR(10)
) ON [PRIMARY]
GO
INSERT INTO CostCategory
VALUES
(1, 'A'), (2, 'B'), (3, 'C')
GO
DROP TABLE IF EXISTS HumanResource;
GO
CREATE TABLE HumanResource
(
IDHR INT
,IDCostCategory INT
) ON [PRIMARY]
GO
INSERT INTO HumanResource
VALUES
(1, 1), (2, 2), (3, 2)
GO
DROP TABLE IF EXISTS HRPlan;
GO
CREATE TABLE HRPlan
(
IDHRPlan INT
,IDHR INT
,Amount INT
,Month INT
,Year INT
) ON [PRIMARY]
GO
INSERT INTO HRPlan
VALUES
(1, 1, 10 , 1, 2019)
, (2, 1, 12 , 2, 2019)
, (3, 1, 15 , 2, 2019)
, (4, 2, 50 , 1, 2019)
, (5, 2, 0 , 2, 2019)
, (6, 2, 100 , 3, 2019)
, (4, 3, 40 , 1, 2019)
, (5, 3, 50 , 2, 2019)
, (6, 3, 30 , 3, 2019)
GO
Для отслеживания производительности вы можете включить статистику операций ввода-вывода и времени:
SET STATISTICS IO ON;
SET STATISTICS TIME ON;
Решение 1: использование внешнего применения (более высокая производительность, чем решение № 2 ниже)
SELECT CC.CostCategory, ISNULL(OA.Amount, 0)
FROM CostCategory CC
OUTER APPLY (
SELECT Amount = SUM(ISNULL(HP.Amount, 0))
FROM HRPlan HP
WHERE HP.Month BETWEEN 1 AND 3
AND HP.Year = 2019
AND EXISTS (
SELECT 1
FROM HumanResource HR
WHERE HR.IDCostCategory = CC.IDCostCategory
AND HR.IDHR = HP.IDHR
)
) OA;
Решение 2: Использование левого соединения
SELECT CC.CostCategory, ISNULL(SUM(HP.Amount), 0)
FROM CostCategory CC
LEFT JOIN HumanResource HR
ON CC.IDCostCategory = HR.IDCostCategory
LEFT JOIN HRPlan HP
ON HR.IDHR = HP.IDHR
AND HP.Month BETWEEN 1 AND 3
AND HP.Year = 2019
GROUP BY CC.CostCategory;
Примечание: — Вы можете подумать о создании индекса columnstore в таблице HRPlan и создать индекс Rowstore/Columnstore в двух других таблицах, который охватывает соединения и выбранные столбцы для повышения производительности.
большое спасибо, 1-е решение было лучшим, если я вычислил количество 4 столбцов.
просто информация, в решении 1 вам нужно добавить «GROUP BY CC.CostCategory» после «OA»
@MedAmin, нет. Если вы добавите туда GROUP BY, запрос выдаст ошибку, так как во внешнем запросе не выполняется агрегация. Агрегация выполняется в части запроса OUTER APPLY. Если у вас есть дубликаты в таблице CostCategory, вам лучше использовать DISTINCT в запросе.
Столбец 'cost_category.CostCategory' недопустим в списке выбора, поскольку он не содержится ни в агрегатной функции, ни в предложении GROUP BY. так что это ошибка, мне нужно использовать GROUP BY, чтобы показать результаты.
@MedAmin, 1> Пожалуйста, перейдите сюда и запустите то же самое в SQL Server: sqlfiddle.com/#!18/d5627/2
@MedAmin 2> Приведенное выше решение относится к данной проблеме. Если у вас больше столбцов или фактический запрос, который вы пытаетесь написать, отличается, или вы пытаетесь выполнить дополнительную агрегацию, запрос необходимо изменить соответствующим образом. Пожалуйста, опубликуйте отдельный вопрос в StackOverflow, если ваше требование отличается от опубликованного здесь. 3> После того, как вы использовали псевдоним для имени таблицы, вам нужно использовать псевдоним для ссылки на столбец в вашем выборе (в случае, если это ваша проблема)
он покажет только записи со значениями, и я хочу показать все записи даже с нулевой суммой