【问题标题】:SQL Server 2012: Dynamic crosstab in stored procedureSQL Server 2012:存储过程中的动态交叉表
【发布时间】:2020-04-10 03:24:01
【问题描述】:

我试图使用存储过程在两个声明的变量@rvar(作为行变量)和@cvar(作为列变量)之间创建一个数据透视表。关键是在执行存储过程时使用这两个作为动态输入从 VBA 调用存储过程。

我的代码分为三部分:

  1. 创建测试数据
  2. 声明本地人
  3. 在交叉表中查找列名并存储在新的本地 @sql1 中
  4. 使用存储在@sql1 中的名称使用pivotfunction 执行交叉表。

My problem: 下面的代码有效,但我想让它动态定义列结构的变量 - 当前设置为“q10_1_resp” - 这样我只需要声明本地 @ cvar 并在第 3 部分中使用它(如第 4 部分)。我已经成功地将第 3 部分变成了一个 sql-string 并随后执行,但是存储在@sql1 中的列名不能在第 4 部分的代码中使用(我猜这是一个范围的事情)。

--Part 1

create table [user].[test]
    (rowvar nvarchar(max),
    q10_1_resp int,
    q10_2_resp int)
    GO 

INSERT [user].[test]
        VALUES ('PH',1,2),
            ('PH',2,3),
            ('EA',1,5),
            ('EA',5,4),
            ('PH',3,4),
            ('PH',6,6),
            ('EA',4,1),
            ('PH',5,3),
            ('PH',2,1)
        GO

-- Part 2
declare @rvar as nvarchar(max) = 'rowvar'
declare @cvar as nvarchar(max) = 'q10_1_resp' --this input should be dynamic as well
declare @sql1 as nvarchar(max)= ''
declare @sql2 as nvarchar(max)= ''

-- Part 3
select @sql1 = @sql1 + [a].[col] + char(44)
    from
        (select distinct QUOTENAME(q10_1_resp) as [col]
        from [user].[test]
        group by q10_1_resp) as a

SET @sql1 = left(@sql1, len(@sql1) - 1)

-- Part 4
SET @sql2 = 'select ' +
    + @rvar + ','
    + @sql1 
    + ' from (Select '
    + @rvar + ', ' 
    + @cvar
    + ' from [user].[test]) sq pivot(count(' 
    + @cvar 
    + ') for '
    + @cvar + ' IN (' 
    + @sql1 
    + ')) as pt'

exec sp_executesql @sql2

【问题讨论】:

  • 我们可以针对您的问题运行的示例数据和预期结果将帮助我们帮助您。 SO上有很多Dynamic Pivots的例子;这些都没有帮助吗?
  • 另外,这里的不是交叉表,而是PIVOT 查询。尽管 2 实现了相同的结果,但交叉表的限制要小得多。
  • 这些示例没有帮助,因为在我看来,您仍然必须在存储过程中对列名进行硬编码(我想通过将其设为本地来避免这种情况)。跨度>
  • 什么例子?你还没有链接到任何;或回复我的任何 cmet。
  • 像这个例子 [stackoverflow.com/questions/10404348/… - 在这里你仍然需要手动输入“c.category”。还是我的意思不清楚?

标签: tsql sql-server-2012 local


【解决方案1】:

在大量尝试全球化标量变量但没有成功之后,使用临时表来存储字符串是关键。在存储过程开始时创建的临时表可以在整个过程中分配和引用。因此在@sql 的执行中分配,然后在@sql2 的执行中引用字符串。我希望这是有道理的。

CREATE PROCEDURE [dbo].[sp_crosstab] 
    -- Add the parameters for the stored procedure here
    @rvar nvarchar(max) = '',
    @cvar nvarchar(max) = '',
    @data nvarchar(max) = '',
    @sql nvarchar(max) = '',
    @sql2 nvarchar(max) = '',
    @sql3 nvarchar(max)=''
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

create table #temp_crosstab
(
   sqlstr nvarchar(max)
)

set @sql ='
declare @sql1 nvarchar(max) = char(00)
select @sql1 = @sql1 + [a].[col] + char(44)
    from
        (select distinct QUOTENAME(' + @cvar + ') as [col]
        from ' + @data + '
        group by ' + @cvar + ') as a

    SET @sql1 = left(@sql1, len(@sql1) - 1)


insert into #temp_crosstab values (@sql1)'

execute sp_executesql @sql


select @sql3 = [sqlstr] from #temp_crosstab

set @sql2 = '

select ' + @rvar + char(44) +
        @sql3 + 'from (Select '
        + @rvar + char(44) + ' ' 
        + @cvar
        + ' from ' + @data + ') sq pivot(count(' 
        + @cvar 
        + ') for '
        + @cvar + ' IN ('+@sql3+')) as pt'


exec sp_executesql @sql2
    END
GO

【讨论】:

    猜你喜欢
    • 2012-02-28
    • 1970-01-01
    • 2016-11-11
    • 1970-01-01
    • 1970-01-01
    • 2013-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多