Как обработать данные во время выборки?
Подскажите, пожалуйста, есть ли возможность в T-SQL (MS SQL) разбить запрос на отдельные "блоки" для обработки каждого "блока" в процессе выборки?
Создаем тестовую табличку
Drop table test_task_table
create table test_task_table (
id bigint primary key,
location VARCHAR(MAX) not null,
end_date_plan DATETIME not null,
fullname VARCHAR(MAX) not null,
status VARCHAR(MAX) not null
);
Добавляем данные
insert into test_task_table values (1, 'Омск', '2024-05-16 00:00:00.000', 'Test H.', 'Назначена');
insert into test_task_table values (2, 'Ростов-на-Дону', '2025-04-26 00:00:00.000', 'Test H.', 'работе');
insert into test_task_table values (3, 'Комсомольск-на-Амуре', '2024-11-29 00:00:00.000', 'Test H.', 'Назначена');
insert into test_task_table values (4, 'Омск', '2025-02-26 00:00:00.000', 'Test H.', 'В работе');
insert into test_task_table values (5, 'Чебоксары', '2025-04-25 00:00:00.000', 'Кравцова И.', 'Завершена');
insert into test_task_table values (6, 'Оренбург', '2023-10-13 00:00:00.000', 'Test H.', 'Назначена');
Выборка
SELECT
task_test.location,
task_test.fullname,
task_test.status,
CAST(YEAR(task_test.end_date_plan) AS VARCHAR(4)) + '_' + CAST(DATEPART(QUARTER, task_test.end_date_plan) AS VARCHAR(1)) AS year_quarter
FROM test_task_table AS task_test
ORDER BY year_quarter
Полученный результат выборки
Желаемый результат: Разделить кварталы пустой строкой, что бы легче обрабатывать дальше на сервере.
Ответы (1 шт):
В качестве шутки) Да, конечно можно, но выглядит, как дикий костыль, просто в виде академического интереса посмотрите:
Вариант с GROUPING SETS + ROLLUP:
SELECT IIF(GROUPING(location)=1,year_quarter,location)location, fullname, status, year_quarter
FROM test_task_table CROSS APPLY(
SELECT CONCAT(YEAR(end_date_plan),'_',(MONTH(end_date_plan)-1)/3+1)
)C(year_quarter)
GROUP BY GROUPING SETS(ROLLUP(year_quarter), (year_quarter, location, fullname, status))
HAVING GROUPING(year_quarter) = 0
ORDER BY year_quarter, GROUPING(location) DESC
Как по мне, долго разбираться, и человек, который потом в этот код будет смотреть - дольше разбираться, будет... Т.е. высокий порог вхождения. Вариант чуть более понятный, но и более громоздкий:
SELECT --выбыиаем что показывать: данные/заголовки
CHOOSE(Typ, location, year_quarter) location,
CHOOSE(Typ, fullname) fullname,
CHOOSE(Typ, status) status,
CHOOSE(Typ, year_quarter) year_quarter
FROM(
SELECT *,
-- нумерация без сортировки, для заголовка нужна любая строка в группе, возьмём первую
ROW_NUMBER()OVER(PARTITION BY year_quarter ORDER BY(SELECT 1))RN
FROM test_task_table CROSS APPLY(
SELECT CONCAT(YEAR(end_date_plan),'_',(MONTH(end_date_plan)-1)/3+1)
)C(year_quarter)
)T --соединяем с табличкой 1,2 - для данных и заголовков
JOIN (VALUES(1),(2))V(typ) -- typ=2 - заголовок, typ=1 - данные
ON RN=1 OR typ=1 -- заголовок или данные
ORDER BY T.year_quarter, typ DESC -- сначала заголовок =2, потом данные=1
Результат один и тот же:


