Установить основанный запрос для замены цикла, чтобы заполнить все даты окончания месяца с данной даты для всех записей - PullRequest
0 голосов
/ 24 декабря 2018

У меня есть таблица, в которой хранятся результаты лабораторных анализов пациентов.Могут быть результаты нескольких тестов, таких как альбумин, калий, фосфор и т. Д. Первое чтение для каждого пациента из каждой из этих категорий сохраняется в таблице с именем # MetricFirstGroupReading.

CREATE TABLE #MetricFirstGroupReading (Patient_Key INT, Metric_Group VARCHAR(100), 
                                       Observation_Date DATE)
ALTER TABLE #MetricFirstGroupReading 
ADD CONSTRAINT UQ_MetricFirst UNIQUE (Patient_Key, Metric_Group);

INSERT INTO #MetricFirstGroupReading
SELECT 1, 'Albumin', '2018-11-15' UNION
SELECT 1, 'Potassium', '2018-12-10' UNION
SELECT 2, 'Albumin', '2018-10-20' UNION
SELECT 2, 'Potassium', '2018-11-25'

Теперь мне нужно заполнить вседаты окончания месяца до текущего месяца в новую таблицу для каждой записи из таблицы #MetricFirstGroupReading.Ниже приведен ожидаемый результат при выполнении запроса в декабре 2018 года.

enter image description here

Я знаю, как это сделать с помощью циклов WHILE.Как сделать это без циклов, используя наборы SQL-запросов в SQL Server 2016?

Ответы [ 3 ]

0 голосов
/ 25 декабря 2018

Как насчет:

    select MetricFirstGroupReading.*, datediff(month, MetricFirstGroupReading.Observation_Date, months.monthendval) monthdiff, months.* 
    into allmonths
    from
    (
    SELECT 1 patientid, 'Albumin' test, '2018-11-15' Observation_Date UNION
    SELECT 1 patientid, 'Potassium' test, '2018-12-10' Observation_Date UNION
    SELECT 2 patientid, 'Albumin' test, '2018-10-20' Observation_Date UNION
    SELECT 2 patientid, 'Potassium' test, '2018-11-25' Observation_Date) MetricFirstGroupReading 
join 
    (
    select '2018-10-31' monthendval union
    select '2018-11-30' monthendval union
    select '2018-12-31' monthendval 
    ) months on MetricFirstGroupReading.Observation_Date< months.monthendval

Заменить первое объединение выбора на вашу таблицу и добавить или удалить окончания месяца из второго внутреннего выбора.

0 голосов
/ 25 декабря 2018

Подумайте о создании временной таблицы из всех дат окончания 12 месяцев, затем присоединитесь к основной таблице по диапазону дат.Используйте DateDiff для разницы за месяц:

CREATE TABLE #MonthEndDates (Month_End_Value DATE)

INSERT INTO #MonthEndDates
VALUES ('2018-01-31'),
       ('2018-02-28'),
       ('2018-03-31'),
       ('2018-04-30'),
       ('2018-05-31'),
       ('2018-04-30'),
       ('2018-06-30'),
       ('2018-07-31'),
       ('2018-08-31'),
       ('2018-09-30'),
       ('2018-10-31'),
       ('2018-11-30'),
       ('2018-12-31')

SELECT m.Patient_Key, m.Metric_Group, m.Observation_Date, 
       DateDiff(month, m.Observation_Date, d.Month_End_Value) AS Month_Diff, 
       d.Month_End_Value

FROM #MetricFirstGroupReading m
INNER JOIN #MonthEndDates d
  ON m.Observation_Date < d.Month_End_Value

GO

Rextester Demo

0 голосов
/ 24 декабря 2018

подписка сработала.Это расширение идеи, представленной в tsql: Как получить последнюю дату каждого месяца между заданным диапазоном дат

Запрос

CREATE TABLE #AllMonthEnds (MonthEndDate DATE)
DECLARE @Start datetime
DECLARE @End datetime

SELECT @Start = '2000-01-01'
SELECT @End = DATEADD(MONTH,1,GETDATE())
;With CTE as
(
    SELECT @Start  as Date,Case When DatePart(mm,@Start)<>DatePart(mm,@Start+1) then 1 else 0 end as [Last]
    UNION ALL
    SELECT Date+1,Case When DatePart(mm,Date+1)<>DatePart(mm,Date+2) then 1 else 0 end from CTE
    WHERE Date<@End
)

INSERT INTO #AllMonthEnds
SELECT [Date]
FROM CTE
WHERE [Last]=1   
OPTION ( MAXRECURSION 0 )



SELECT  T.Patient_Key, T.Metric_Group, T.Observation_Date AS First_Observation_Date,
        DATEDIFF(MONTh,Observation_Date, MonthEndDate) AS MonthDiff, 
         A.MonthEndDate AS IterationDate
FROM #AllMonthEnds A
INNER JOIN
(
    SELECT *, ROW_NUMBER() OVER(PARTITION BY Patient_Key, Metric_Group ORDER BY Observation_Date) AS RowVal
    FROM #MetricFirstGroupReading M
)T
    ON A.MonthEndDate >= T.Observation_Date
WHERE RowVal = 1
ORDER BY Patient_Key, Metric_Group, T.Observation_Date, A.MonthEndDate
...