Как в переменную поместить список? Заносится только последняя запись, а мне нужен весь список MSSQL

Выполняю задание по T-SQL: Процедура, вызывающая вложенную процедуру, которая подсчитывает среднее количество часов в год по дисциплинам, и выдающая список дисциплин с количеством часов в год меньше среднего

Вложенная процедура:

create proc p4_1 @avgH int output
as
begin
select @avgH = avg(Количество_часов)
from Учебный_план join Преподавание on Учебный_план.Код_Предмета=Преподавание.Код_Предмета 
join Преподаватель on Преподавание.Id_Преподавателя=Преподаватель.Id_Преподавателя 
group by Преподавание.Id_Преподавателя
end

Результат:

введите сюда описание изображения

основная процедура:

create proc p4 
as
begin
declare @Hour int
exec p4_1 @avgH=@Hour output
select Дисциплина from Учебный_план
where Количество_часов<@Hour
end

Результат выдает неверный, так как в переменную @avgH(процедура p4_1) записывается только последняя запись(65), как мне сделать так, чтобы сравнивалось со всем спискам и подбирало дисциплины исходя из всего списка, а не сравнивая с 65 часами.


Ответы (1 шт):

Автор решения: Yitzhak Khabinsky

Вам нужно вернуть массив из первой хранимой процедуры. Это может быть XML или JSON.

Попробуйте следующий концептуальный пример. Он будет работать, начиная с SQL Server 2005 и новее.

CTE делает то, что должна делать ваша первая хранимая процедура. Он возвращает тип данных XML со всеми необходимыми данными. После этого мы конвертируем XML в реляционный формат и с помощью INNER JOIN отфильтровываем записи в основной таблице.

SQL

-- DDL and sample data population, start
DECLARE @tbl_averages TABLE (avg_hour INT);
INSERT INTO @tbl_averages VALUES 
(126),
(144),
(108);

DECLARE @tbl_studyPlan TABLE (ID INT IDENTITY PRIMARY KEY, study_hour INT);
INSERT INTO @tbl_studyPlan (study_hour) VALUES
(90),
(100),
(770);
-- DDL and sample data population, end

;WITH rs (xmldata)AS
(
    SELECT * FROM @tbl_averages
    FOR XML PATH(''), TYPE, ROOT('root')
)
SELECT DISTINCT studyPlan.*
FROM @tbl_studyPlan AS studyPlan INNER JOIN 
    (SELECT avg_hour = c.value('.', 'INT') 
        FROM rs CROSS APPLY xmldata.nodes('/root/avg_hour/text()') AS t(c)
    ) AS seq
    ON studyPlan.study_hour < seq.avg_hour;

Результат

+----+------------+
| ID | study_hour |
+----+------------+
|  1 |         90 |
|  2 |        100 |
+----+------------+
→ Ссылка