【问题标题】:Getting dynamic query select fields to show in Crystal Reports获取要在 Crystal Reports 中显示的动态查询选择字段
【发布时间】:2019-11-07 09:28:21
【问题描述】:

我有一个我认为非常复杂的查询(至少对我而言),我决定尝试使用动态 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 PROCEDURE 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 Reports 中创建报表结合使用。当我导入存储过程时,这些列显示为空白。我查看了以下链接。 [从动态 SQL 查询中选择字段名称][1]

[1]:SELECT fieldnames FROM dynamic SQL query,即使我试图按照所说的完全有效的方法来模拟我的答案。它似乎对我不起作用,因为我的数据列在 Crystal 中仍然是空白的。

我有从一个单独的存储过程调用我的第一个存储过程的想法,但给出了我的答案是如何返回的(不仅仅是我可以分配给变量的单个值,目前正在考虑返回一个表值函数)我怀疑这是否可行。

出现的第二个问题是因为我的“周”是动态的(最多 6 周)我无法创建带有“备用”列的临时表,或者我收到错误(列数不正确),正如你所看到的我评论他们出去,我也不能使用“选择进入”

感谢提供的任何帮助或想法。

【问题讨论】:

    标签: sql-server tsql crystal-reports sql-server-2008-r2


    【解决方案1】:

    尝试以下,它使用全局 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
    

    【讨论】:

    • 如果两个人调用这个不会导致错误吗?因为临时表?
    猜你喜欢
    • 1970-01-01
    • 2020-12-22
    • 1970-01-01
    • 2013-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多