Динамический SQL, Переходящий за 12 Месяцев.

#sql #sql-server #pivot #dynamic-sql

Вопрос:

Я новичок в динамическом SQL. У меня есть следующая таблица:

Имя заказчика Дата Часов
Первый 01/01/2021 12
Второй 01/01/2021 10
Второй 05/02/2021 1
Второй 10/11/2021 14

Я пытаюсь составить сводный сводный календарь за последние 12 месяцев с суммированными часами.

Вот код, который я сделал:

 DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

    select @cols = STUFF(
    (SELECT distinct ','   QUOTENAME(DATENAME(mm,Date)   ' of ' 
      DATENAME(year,Date)) AS months_ago
          FROM [TimeEntryList]  
          WHERE Date > DATEADD(year, -1, 
    DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1))
    FOR XML PATH(''), TYPE
    ).value('.', 'NVARCHAR(MAX)') 
,1,1,'')


 set @query = 'SELECT CustName, '   @cols   ' 
 from ( select 
   [CustName], 
   datename(mm,[Date]) '' of '' datename(year,[Date])AS 
   months_ago, [Hours] AS NetQty 
   from [TimeEntryList] 
    WHERE [Date] > DATEADD(year, -1, 
  DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1))
 ) as source 
 pivot 
 ( 
 sum(NetQty) For months_ago  in ('   @cols   ')
 ) as PivotTable'

execute sp_executesql @query;
 

Это работает «вроде» так, как я хочу, но столбцы не упорядочены с текущей даты в обратном порядке.

Я хочу, чтобы это началось в текущем месяце задом наперед. Так что если в этом месяце август, то это будет:

Имя заказчика Сентябрь 2020 …. месяцев Август 2021 года
Первый 12 14
Второй 3 12

Есть ли хороший способ начать с текущего месяца в динамическом SQL в сводной таблице и вернуться на 12 месяцев назад?

Я попробовал «заказать по месяцам» и т. Д., Но это не работает

Ответ №1:

Вам просто нужно добавить WHERE фильтр. это должно быть в обеих частях запроса.

 DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX);

SET @cols = STUFF(
    (SELECT ','   QUOTENAME(DATENAME(mm, EOMONTH(Date))   ' of '   DATENAME(year, EOMONTH(Date))) AS months_ago
    FROM [TimeEntryList]  
    WHERE [Date] > DATEADD(year, -1, DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1))
    GROUP BY EOMONTH(Date)
    ORDER BY EOMONTH(Date)
    FOR XML PATH(''), TYPE
    ).value('text()[1]', 'NVARCHAR(MAX)') 
,1,1,'');

SET @query = '
SELECT
  CustName,
  '   @cols   ' 
from (
  select 
    [CustName], 
    datename(mm,[Date]) '' of '' datename(year,[Date])AS months_ago, [Hours] AS 
    NetQty 
   from [TimeEntryList]
   WHERE [Date] > DATEADD(year, -1, DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1))
 ) as source 
pivot 
  ( 
   sum(NetQty) For months_ago  in ('   @cols   ')
  ) as PivotTable;
';

execute sp_executesql @query;
 

Вы даже можете пройти через параметр даты начала, как это:

 DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX),
    @dateFrom datetime;

SET @dateFrom = DATEADD(year, -1, DATEFROMPARTS(YEAR(GETDATE()), MONTH(GETDATE()), 1));

SET @cols = STUFF(
    (SELECT ','   QUOTENAME(DATENAME(mm,EOMONTH(Date))   ' of '   DATENAME(year,EOMONTH(Date)) AS months_ago
    FROM [TimeEntryList]  
    WHERE [Date] > @dateFrom
    GROUP BY EOMONTH(Date)
    ORDER BY EOMONTH(Date)
    FOR XML PATH(''), TYPE
    ).value('text()[1]', 'NVARCHAR(MAX)') 
,1,1,'');

SET @query = '
SELECT
  CustName,
  '   @cols   ' 
from (
  select 
    [CustName], 
    datename(mm,[Date]) '' of '' datename(year,[Date])AS months_ago, [Hours] AS 
    NetQty 
   from [TimeEntryList]
   WHERE [Date] > @dateFrom
 ) as source 
pivot 
  ( 
   sum(NetQty) For months_ago  in ('   @cols   ')
  ) as PivotTable;
';

execute sp_executesql
    @query
    N'@dateFrom datetime',
    @dateFrom = @dateFrom;
 

Комментарии:

1. А — спасибо. По какой-то причине я получаю «ИМЯ ЦИТАТЫ», которое не является встроенной функцией. Если я заключу это в скобки, это исправит ситуацию, но отчет просто выполняется и не отображает данные.

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

3. Я думаю, что все сводится к упорядочению по «динамической» части. Я знаю, как заказывать по дате в обычном SQL, но с этим динамическим примером я думаю, что мне нужно попробовать сделать заказ в «months_ago», который не будет работать. Может быть, мне сначала нужно создать временную сводную таблицу, а затем использовать динамический SQL … может быть … что-то новое в этом.

4. Спасибо! — Я создал его здесь , как вы можете видеть, первым появляется апрель 2021 года.

5. Хорошо, исправил это для тебя dbfiddle.uk/…