【问题标题】:Insert query results into temp table将查询结果插入临时表
【发布时间】:2015-11-12 22:28:08
【问题描述】:

我最近从这里学习了如何在 SQL 中进行 PIVOT,实际上我从这里的另一个问题中举了一个例子。效果很好。

但是,我想在查询之后执行额外的连接,但我无法将查询结果插入临时表?我该怎么做?

创建表

CREATE TABLE yt
([Store] int, [Week] int, [xCount] int)
;
INSERT INTO yt
([Store], [Week], [xCount])
VALUES
(102, 1, 96),
(101, 1, 138),
(105, 1, 37),
(109, 1, 59),
(101, 2, 282),
(102, 2, 212),
(105, 2, 78),
(109, 2, 97),
(105, 3, 60),
(102, 3, 123),
(101, 3, 220),
(109, 3, 87);

执行旋转查询

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

select @cols = STUFF((SELECT ',' + QUOTENAME(Week) 
                from yt
                group by Week
                order by Week
        FOR XML PATH(''), TYPE
        ).value('.', 'NVARCHAR(MAX)') 
    ,1,1,'')


set @query = 'SELECT store,' + @cols + ' from 
         (
            select store, week, xCount
            from yt
        ) x
        pivot 
        (
            sum(xCount)
            for week in (' + @cols + ')
        ) p '


execute(@query)

结果是

store   1   2   3
101 138 282 220
102 96  212 123
105 37  78  60
109 59  97  87

但我想将它放在#temp 表中,我尝试将 INTO #temp 放在“执行查询”之前和查询中的 FROM 语句之前。

有什么想法吗?我知道 SELECT * INTO #temp FROM BlaBla 但似乎与查询不同。

【问题讨论】:

标签: sql sql-server pivot


【解决方案1】:

您在执行中使用select ... into #temp 面临的问题是该表已创建,但由于位于单独的范围内,它在执行结束时立即被删除,因此您的过程看不到它。

如果您在调用执行之前创建表并仅使用 insert into,您的代码将起作用。您可以在SQL Fiddle 中查看。这只会导致问题,如果您的查询是动态的,如何创建表以使其适合查询。

尝试创建动态调整 SQL 中列数的逻辑并不容易,而且确实不是您应该做的事情。更好的方法是在您的表示层中处理它。

【讨论】:

  • 结果集有一组动态列,这就是 OP 使用动态 sql 进行数据透视的原因。如果该表超出范围,您将如何创建一个动态定义的表? 不会,这通常是一种代码味道,需要动态 sql 来透视表,这向我建议该表应保持其规范化形式。)
  • @MatBailie 没错,这就是我想说的。
【解决方案2】:

您可以动态创建全局临时表

  declare @tblName nvarchar(10)
  set @tblName = N'##Temp' + cast(@@spid as nvarchar(5))
  declare @tblCreate nvarchar(max)
  SET @tblCreate = N'create table ' + @tblName + ' (' 
  + REPLACE(@cols,',',' int,') + N' int)'

  EXECUTE sp_executesql @tblCreate

然后编辑您的@query 以插入到表中。

set @query = 'INSERT INTO ' + @tblName + ' SELECT store,' + @cols + ' from 
         (
            select store, week, xCount
            from yt
        ) x
        pivot 
        (
            sum(xCount)
            for week in (' + @cols + ')
        ) p; 
        drop table ' + @tblName


execute(@query)

【讨论】:

  • @MatBailie 全局临时表将保留在范围内
  • 抱歉,没有注意到##,我很抱歉。应该注意的是,所有用户/会话都会看到这个表,并发可能会成为一个问题。
  • @MatBailie 这是真的。 ##Temp 可能不是它的最佳名称,更独特的东西会更好
  • 无论如何,并发将是一个问题。同时运行此 SP 的两个用户都将尝试创建和使用全局临时表,但名称相同且定义可能不同。也许在名称中使用@@spid?
猜你喜欢
  • 2015-05-03
  • 1970-01-01
  • 2020-12-05
  • 1970-01-01
  • 1970-01-01
  • 2014-10-20
  • 1970-01-01
  • 2015-03-05
  • 2020-01-26
相关资源
最近更新 更多