Как обработать данные во время выборки?

Рейтинг: 1Ответов: 1Опубликовано: 28.02.2025

Подскажите, пожалуйста, есть ли возможность в 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

Полученный результат выборки

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

Желаемый результат: Разделить кварталы пустой строкой, что бы легче обрабатывать дальше на сервере.

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

Ответы

▲ 2

В качестве шутки) Да, конечно можно, но выглядит, как дикий костыль, просто в виде академического интереса посмотрите:

Вариант с 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

Результат один и тот же:

Результат