Как я могу заполнить таблицу с шагом в один месяц на основе даты - PullRequest
0 голосов
/ 15 апреля 2019

Мне нужно загрузить таблицу на основе даты ввода из другой таблицы, которая находится между 1-м днем ​​месяца и последним днем ​​месяца. Мне нужно уменьшить нагрузку, чтобы она составляла 1 месяц записей: 1 месяц от текущего месяца, затем 2 месяца от текущего месяца и т. Д.

Я пробовал CTE, используя курсор и вручную изменяя параметры датированных значений. Этот последний метод работает, но я хотел бы загрузить таблицу динамически

Declare @StartDt as datetime = (SELECT FORMAT(DATEADD(s,0,DATEADD(mm, DATEDIFF(m,0,GETDATE())-1,0)),'MM/dd/yyyy'));

Declare @endDt as datetime = EOMONTH(@StartDt);

SELECT  useruid, 
    userfullname,
    sum(totaltime)SumTime,
    @StartDt as StartDate, 
    @EndDt as EndDate

FROM Table_1.tbl
WHERE ENTRYDATE between @StartDt  and @EndDt
group by useruid, USERFULLNAME;

Я вставляю это в другую таблицу. У меня нет проблем с этим путем ручного изменения -1 в переменной Startdt на -2 и так далее. Я хочу знать, могу ли я динамически изменить его при загрузке другой таблицы.

Опять же, у меня нет проблем с загрузкой таблицы. Я просто хочу знать, есть ли более эффективный способ сделать это, так как мне нужно вернуться на 100 месяцев назад.

Ответы [ 2 ]

1 голос
/ 15 апреля 2019

Один метод является рекурсивным CTE:

with dates as (
      select datefromparts(year(getdate()), month(getdate()), 1) as dte
      union all
      select dateadd(month, -1, dte)
      from dates
      where dte > ?  -- how far back do you want to go?
     )
select t.useruid, t.userfullname, sum(t.totaltime) as SumTime,
       d.dte as StartDate, 
       dateadd(month, 1, d.dte) as EndDate
from dates d JOIN
     Table_1.tbl t
     on t.ENTRYDATE >= d.dte AND
        t.ENTRYDATE < dateadd(month, 1, d.dte) 
group by t.useruid, t.USERFULLNAME, d.dte;

Вам не нужен (явный) цикл или курсор.

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

0 голосов
/ 15 апреля 2019

Вы можете использовать динамический SQL, чтобы написать оператор объявления @StartDt на лету.

Я поместил ваш код в цикл while, который будет выполняться 100 раз.(100 месяцев назад):

declare @int int = 0
while @int > -100
begin
set @int= @int -1
declare @str varchar(max)
set @str = 'declare @StartDt as datetime = (SELECT FORMAT(DATEADD(s,0,DATEADD(mm, DATEDIFF(m,0,GETDATE())'+cast(@int as varchar(10))+',0)),''MM/dd/yyyy''))'
execute (@str)

Declare @endDt as datetime = EOMONTH(@StartDt)

SELECT  useruid, 
    userfullname,
    sum(totaltime)SumTime,
    @StartDt as StartDate, 
    @EndDt as EndDate

FROM Table_1.tbl
WHERE ENTRYDATE between @StartDt  and @EndDt
group by useruid, USERFULLNAME
end
...