Создайте функцию/процедуру SQL из 3 таблиц

У меня есть 3 таблицы, категория, человеческий ресурс и план управления персоналом.

Создайте функцию/процедуру SQL из 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, так как год и месяц будут вставлены в качестве параметра.

ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
0
0
165
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

для повышения производительности вы можете избежать предложения 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 

он покажет только записи со значениями, и я хочу показать все записи даже с нулевой суммой

Med Amin 22.06.2019 14:46

Я не думаю, что этот запрос даст то, о чем просят. Порядок соединения должен быть изменен. Вы можете взглянуть на 2 решения, которые я предоставил ниже, и дайте мне знать.

san 24.06.2019 07:43
Ответ принят как подходящий

Наличие 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 столбцов.

Med Amin 24.06.2019 12:05

просто информация, в решении 1 вам нужно добавить «GROUP BY CC.CostCategory» после «OA»

Med Amin 24.06.2019 19:02

@MedAmin, нет. Если вы добавите туда GROUP BY, запрос выдаст ошибку, так как во внешнем запросе не выполняется агрегация. Агрегация выполняется в части запроса OUTER APPLY. Если у вас есть дубликаты в таблице CostCategory, вам лучше использовать DISTINCT в запросе.

san 24.06.2019 19:10

Столбец 'cost_category.CostCategory' недопустим в списке выбора, поскольку он не содержится ни в агрегатной функции, ни в предложении GROUP BY. так что это ошибка, мне нужно использовать GROUP BY, чтобы показать результаты.

Med Amin 26.06.2019 13:24

@MedAmin, 1> Пожалуйста, перейдите сюда и запустите то же самое в SQL Server: sqlfiddle.com/#!18/d5627/2

san 27.06.2019 06:09

@MedAmin 2> Приведенное выше решение относится к данной проблеме. Если у вас больше столбцов или фактический запрос, который вы пытаетесь написать, отличается, или вы пытаетесь выполнить дополнительную агрегацию, запрос необходимо изменить соответствующим образом. Пожалуйста, опубликуйте отдельный вопрос в StackOverflow, если ваше требование отличается от опубликованного здесь. 3> После того, как вы использовали псевдоним для имени таблицы, вам нужно использовать псевдоним для ссылки на столбец в вашем выборе (в случае, если это ваша проблема)

san 27.06.2019 06:17

Другие вопросы по теме