Динамически создавать столбцы таблицы со значениями из сводной таблицы - PullRequest
0 голосов
/ 25 июня 2019

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

Status 1  | Week 1 |25
Status 1  | Week 1 |25
Status 1  | Week 2 |25
Status 2  | Week 1 | 2
Status 2  | Week 1 | 8
Status 2  | Week 1 | 10
Status 2  | Week 1 | 10 

и это пример того, как данные возвращаются.

            Week 1        Week 2    
Status 1 |    50            25
Status 2      10            20

Для моего запроса я прохожу через неделю и хочу развернуться на следующие 5 недель, поэтому, например, если я перейду на 1, у меня будут столбцы с 1 по 6 неделю. Чтобы облегчить это, я написал следующий запрос.

--EXEC usp_weekReport @weeks=1, @year='2019'
ALTER PROC usp_weekReport
(
@weeks INT,
@year NVARCHAR(4)

)
AS
DECLARE @columns NVARCHAR(MAX), @sql NVARCHAR(MAX), @csql NVARCHAR(MAX);
SET @columns = N'';
SELECT @columns += N', p.' + QUOTENAME([week]) 
  FROM (
  SELECT p.[week] 
  FROM [Housing_support_DB].[dbo].[Invoices] P 
  WHERE DATEPART(YEAR,P.date)='2019'--@year
  AND 
  ([week] IN (1)
  OR
  [week] IN (1+1)
    OR
  [week] IN (1+2)
    OR
  [week] IN (1+3)
    OR
  [week] IN (1+4)
    OR
  [week] IN (1+5) 
  )
  GROUP BY P.[week] 

  ) AS x;
SET @sql = N'
SELECT p.[statusName],' + STUFF(@columns, 1, 2, '') + '
FROM
(
  SELECT 
    SUM(CAST(REPLACE(REPLACE(A.amount,'','',''''),''$'','''') AS FLOAT)) as sumInvoice,
  A.invoiceStatusID_FK,
  B.statusName,
--  C.programme,
  [week]
  FROM [dbo].[Invoices] A
  INNER JOIN invoiceStatus B
  ON A.invoiceStatusID_FK=B.invoiceStatusID
--  INNER JOIN CapitalAccountBalances C
 -- ON C.accountBalanceID=A.accountBalanceID_FK 
 -- WHERE A.accountBalanceID_FK=5
 GROUP BY invoiceStatusID_FK,B.statusName,[week]--,C.programme
) AS j
PIVOT
(
  SUM(sumInvoice) FOR [week] IN ('
  + STUFF(REPLACE(@columns, ', p.[', ',['), 1, 1, '')
  + ')
) AS p;';
--PRINT @sql;
EXEC sp_executesql @sql;
--SET @csql = N'
--CREATE TABLE ##reportResult
--(
--statusName nvarchar(50),'+
CREATE TABLE ##reportResult
(
statusName nvarchar(50),
weekA INT DEFAULT 0,
 weekB int DEFAULT 0--,
--weekC int DEFAULT 0,
--weekD int DEFAULT 0,
--weekE int DEFAULT 0,
--weekF int DEFAULT 0
)
 INSERT  into  ##reportResult Exec(@sql)
--INSERT ##reportResult Exec(@sql)
--SELECT statusName, weekA,weekB,weekC,weekD,weekE,weekF -- here you have "static SELECT with field names"
--FROM ##reportResult 
--DROP TABLE ##reportResult

Задача

Огромная проблема, с которой я столкнулся, заключается в том, что мне нужно отправить результат этого запроса в tempTable ... # reportResult. В результате мне нужно создать таблицу. Однако, если я попытаюсь создать таблицу с ожидаемым максимальным количеством столбцов (6), я получу ошибочное количество столбцов с ошибкой. Например, в моей базе данных у меня есть только две недели, поэтому я могу только создать таблицу со столбцами weekA и weekB. Я также не могу сделать выбор в.

В настоящее время я пытаюсь найти способ динамического создания таблицы в зависимости от количества недель, прошедших с первой части сводной таблицы. Или, чтобы манипулировать первой частью сводки, чтобы выбрать неделю, неделю + 1 и т. Д. В качестве столбцов при запуске таким образом, я могу создать столбец со всеми полями.

Ценю любую помощь, которая может быть оказана.

1 Ответ

0 голосов
/ 25 июня 2019

В вашем случае вам необходим динамический SQL, так как имя столбца необходимо генерировать на основе номера недели ввода. Ниже я дам вам сценарий, который я создал с вашими примерами данных с использованием CTE. Вам просто нужно обновить скрипт на основе вашей таблицы и требований.

Вы можете проверить код, изменив значение Week_No

Для окончательного запроса просто используйте часть SELECT после удаления кода CTE

DECLARE @Week_No INT = 2
DECLARE @Loop_Count INT = 1
DECLARE @Column_List VARCHAR(MAX) = '[Week '+CAST(@Week_No AS VARCHAR) +']'

WHILE @Loop_Count < 5
BEGIN
    SET @Column_List = @Column_List +',[Week '+CAST(@Week_No+@Loop_Count AS VARCHAR) +']'
    SET @Loop_Count = @Loop_Count + 1
END

--SELECT @Column_List
EXEC
('
    WITH your_table(Status,Week_No,Val)
    AS
    (
    SELECT ''Status 1'',''Week 1'',25 UNION ALL
    SELECT ''Status 1'',''Week 1'',25 UNION ALL
    SELECT ''Status 1'',''Week 2'',25 UNION ALL
    SELECT ''Status 2'',''Week 1'',2 UNION ALL
    SELECT ''Status 2'',''Week 1'',8 UNION ALL
    SELECT ''Status 2'',''Week 1'',10 UNION ALL
    SELECT ''Status 2'',''Week 1'',10 
    )


    SELECT * FROM
    (
        SELECT * FROM your_table
    ) AS P
    PIVOT
    (
        SUM(val)
        FOR Week_No IN ('+@Column_List+')
    )PVT
') 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...