Получение динамического запроса, выберите поля для отображения в отчетах Crystal. - PullRequest
0 голосов
/ 25 июня 2019

У меня есть довольно сложный запрос (по крайней мере для меня), и я решил попытаться решить его с помощью динамического SQL.Однако у меня есть две проблемы, которые мне не удалось решить.

Ситуация

В таблице пользователь может ввести элемент, который имеет сумму, неделю и статус.Таким образом, данные должны напоминать этот формат.

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

И это данные в SQL.

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

Для каждого статуса я суммирую сумму, основанную на неделях, с использованием динамического центраТаблица.

Что я пытался

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

)
AS
DECLARE @columns NVARCHAR(MAX), @sql NVARCHAR(MAX);
SET @columns = N'';
SELECT @columns += N', p.' + QUOTENAME([week])
  FROM (
  SELECT p.[week] 
  FROM [dbo].[Invoices] P
  WHERE DATEPART(YEAR,P.date)=@year
  AND 
  ([week] IN (@weeks)
  OR
  [week] IN (@weeks+1)
    OR
  [week] IN (@weeks+2)
    OR
  [week] IN (@weeks+3)
    OR
  [week] IN (@weeks+4)
    OR
  [week] IN (@weeks+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,
  [week]
  FROM [dbo].[Invoices] A
  INNER JOIN invoiceStatus B
  ON A.invoiceStatusID_FK=B.invoiceStatusID
 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;


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 #reportResult Exec(@sql)
SELECT statusName, weekA,weekB--,weekC,weekD,weekE,weekF -- here you have "static SELECT with field names"
FROM #reportResult 
DROP TABLE #reportResult

Чтобы решить эту проблему, у меня есть приведенный выше код и пока он работает (возвращает значения в SQL) у меня есть двапроблемы.

Проблемы Моя первая проблема заключается в том, что я не могу использовать этот код в сочетании с созданием отчета в отчетах Crystal.Когда я импортирую процедуру сохранения, столбцы отображаются пустыми.Я посмотрел на следующую ссылку.[Выбрать имена полей из динамического SQL-запроса] [1]

[1]: ВЫБРАТЬ имена полей из динамического SQL-запроса и даже если я попытался смоделировать свой ответ после того, что, как было сказано, работает точно,Мне кажется, это не работает, так как мои столбцы данных в Crystal по-прежнему пустые.У меня была идея вызвать мой первый хранимый процесс из отдельного хранимого процесса, но с учетом того, как возвращается мой ответ (не только одно значение, которое я могу присвоить переменной, в настоящее время я думаю о возвращении функции табличного значения) Я сомневаюсь, что этобудет работать.

Вторая проблема, которая возникла, заключается в том, что мои «недели» являются динамическими (до 6 недель). Я не могу создать временную таблицу со столбцами «Spare», или я получаю ошибку (неправильное количество столбцов)Как вы видите, я прокомментировал их, и я также не могу использовать «Выбрать в»

Цените любую помощь или предложенные идеи.

1 Ответ

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

Попробуйте выполнить следующее: используется глобальная таблица TEMP:

ALTER PROCEDURE  usp_weekReport 
    @weeks INT,
    @year  NVARCHAR(4)
AS
BEGIN
    DECLARE @columns NVARCHAR(MAX), @sql NVARCHAR(MAX);

    SET @columns = N'';

    SELECT @columns+=N', p.'+QUOTENAME([week])
     FROM (
          SELECT p.[week]
          FROM [dbo].[Invoices] P
          WHERE DATEPART(YEAR, P.date) = @year
                AND ([week] IN(@weeks)
                OR [week] IN(@weeks + 1)
                OR [week] IN(@weeks + 2)
                OR [week] IN(@weeks + 3)
                OR [week] IN(@weeks + 4)
                OR [week] IN(@weeks + 5))
          GROUP BY P.[week]
       ) AS x;
     SET @sql = N'
                SELECT p.[statusName],'+STUFF(@columns, 1, 2, '')+'
                into ##reportResult
                FROM
                (
                  SELECT 
                    SUM(CAST(REPLACE(REPLACE(A.amount,'','',''''),''$'','''') AS FLOAT)) as sumInvoice,
                  A.invoiceStatusID_FK,
                  B.statusName,
                  [week]
                  FROM [dbo].[Invoices] A
                  INNER JOIN invoiceStatus B
                  ON A.invoiceStatusID_FK=B.invoiceStatusID
                 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;';
 EXEC sp_executesql @sql;
     SELECT *
     FROM ##reportResult;

     IF OBJECT_ID('tempdb..##reportResult') IS NOT NULL
     BEGIN
      DROP TABLE ##reportResult;
     END;
END

Вот решение без глобальной временной таблицы:

ALTER PROCEDURE  usp_weekReport 
    @weeks INT,
    @year  NVARCHAR(4)
AS
BEGIN
    DECLARE @columns NVARCHAR(MAX), @sql NVARCHAR(MAX), @COLCOUNT int, @TableColumns  NVARCHAR(MAX);

    SET @columns = N'';

    SELECT @columns+=N', p.'+QUOTENAME([week])
     FROM (
          SELECT p.[week]
          FROM [dbo].[Invoices] P
          WHERE DATEPART(YEAR, P.date) = @year
                AND ([week] IN(@weeks)
                OR [week] IN(@weeks + 1)
                OR [week] IN(@weeks + 2)
                OR [week] IN(@weeks + 3)
                OR [week] IN(@weeks + 4)
                OR [week] IN(@weeks + 5))
          GROUP BY P.[week]
       ) AS x;

    SELECT @COLCOUNT = count(*)
     FROM (
          SELECT p.[week]
          FROM [dbo].[Invoices] P
          WHERE DATEPART(YEAR, P.date) = @year
                AND ([week] IN(@weeks)
                OR [week] IN(@weeks + 1)
                OR [week] IN(@weeks + 2)
                OR [week] IN(@weeks + 3)
                OR [week] IN(@weeks + 4)
                OR [week] IN(@weeks + 5))
          GROUP BY P.[week]
       ) AS x;


      SELECT @TableColumns = CASE When @COLCOUNT = 1 THEN 'weekA'
                            When @COLCOUNT = 2 THEN 'weekA, weekB'
                            When @COLCOUNT = 3 THEN 'weekA, weekB, weekC'
                            When @COLCOUNT = 4 THEN 'weekA, weekB, weekC, weekD'
                            When @COLCOUNT = 5 THEN 'weekA, weekB, weekC, weekD, weekE'
                            When @COLCOUNT = 6 THEN 'weekA, weekB, weekC, weekD, weekE, weekF'                          
                        end;



      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
       )


     SET @sql = N'
             INSERT INTO #reportResult (statusName,' + @TableColumns +  ')
                SELECT p.[statusName],'+STUFF(@columns, 1, 2, '')+'
                into ##reportResult
                FROM
                (
                  SELECT 
                    SUM(CAST(REPLACE(REPLACE(A.amount,'','',''''),''$'','''') AS FLOAT)) as sumInvoice,
                  A.invoiceStatusID_FK,
                  B.statusName,
                  [week]
                  FROM [dbo].[Invoices] A
                  INNER JOIN invoiceStatus B
                  ON A.invoiceStatusID_FK=B.invoiceStatusID
                 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;';

    EXEC sp_executesql @sql;

     SELECT *
     FROM #reportResult;

     IF OBJECT_ID('tempdb..#reportResult') IS NOT NULL
     BEGIN
      DROP TABLE #reportResult;
     END;
END
...