Sum over SQL,无需分组或排序

时间:2016-01-14 11:22:27

标签: sql sql-server tsql global-temp-tables

我有一个像这样的SQL Server查询:

CREATE TABLE ##Temp(
    OrderID NVARCHAR(100), 
    ID INT,
    Prices INT,
    Total INT
);

INSERT INTO ##Temp (ID, Prices, OrderID, Total)
SELECT  fc.ID, f.Prices, f.OrderID, 
        (SUM(f.Prices) OVER()) AS Total 
FROM FruitCrates fc
LEFT JOIN Fruits f ON fc.ID = f.FruitCrateID
WHERE  fc.OrderID LIKE '18_1635' 
  AND fc.Rights = 1 
  AND fc.Cancelled = 0 
  AND f.OrderID IS NOT NULL;

SELECT * FROM ##Temp;

但我一直收到错误:

  

Msg 207,Level 16,State 1,Line 12
  列名称“总计”无效。

我认为是因为我没有正确使用OVER() 但是我不确定如何修复它。

请注意

SELECT语句在INSERT之后没有放入时就会起作用。

没有INSERT的结果

╔═════╦════════╦══════════╦═══════╗
║ ID  ║ Prices ║ OrderID  ║ Total ║
╠═════╬════════╬══════════╬═══════╣
║  77 ║      1 ║ 1_370    ║   104 ║
║  19 ║    101 ║ 1811_171 ║   104 ║
║  77 ║      2 ║ 1811_171 ║   104 ║
╚═════╩════════╩══════════╩═══════╝   

1 个答案:

答案 0 :(得分:1)

插入Invalid column name 'Total'.的错误消息清楚地表明##Temp表的架构与INSERT INTO (...)语句中的列列表不同。

要对其进行问题排查,您应该在插入之前检查元数据(列名称):

SELECT *
FROM ##Temp
WHERE 1=2;

然后你可以很容易地发现你所假设的不同。

现在您正在使用全局临时表,只要引用它的最后一个连接处于活动状态,它就会存在。您应该考虑使用本地临时表。

要解决您的情况,您可以:

  1. 使用其他名称以避免碰撞
  2. 就在你可以之前(如果没有在嵌套程序中使用):

    IF OBJECT_ID('tempdb..##temp') IS NOT NULL     
    DROP TABLE ##temp
    
    CREATE TABLE ##temp...
    
  3. 当存储过程称为另一个存储过程并且(外部和内部)创建具有相同名称的临时表时,还存在一个令人讨厌的情况。你应该避免它。

    CREATE PROCEDURE #outer
    AS
    BEGIN
       CREATE TABLE ##temp (id INT, guid UNIQUEIDENTIFIER, col2 VARCHAR(100));
       INSERT INTO ##temp VALUES(1,NEWID(), 'a');
       SELECT * FROM ##temp;
       EXEC [#inner];
    END
    GO
    
    CREATE PROCEDURE #inner
    AS
    BEGIN
        CREATE TABLE ##temp (id INT, total INT);  -- no error during creation
    
        INSERT INTO ##temp(id, total)
        SELECT 2, 10;
    
        SELECT * FROM ##temp;
    END
    GO
    
    EXEC #outer
    -- Invalid column name 'total'.
    

    LiveDemo

    最有趣的是当你使用具有相同列数(或默认值)的本地临时表并且隐式强制转换是可能的时,它将通过:

    CREATE PROCEDURE #outer
    AS
    BEGIN
    CREATE TABLE #temp (id INT, col2 varchar(10));
       INSERT INTO #temp VALUES(1, 'a');
       SELECT * FROM #temp;
       EXEC [#inner];
    END
    GO
    
    CREATE PROCEDURE #inner
    AS
    BEGIN
        CREATE TABLE #temp (id INT, total INT);
        INSERT INTO #temp
        SELECT 2, 10;
    
        SELECT * FROM #temp;
    END
    GO
    
    EXEC #outer
    

    LiveDemo2

    不兼容类型的示例:

    CREATE PROCEDURE #outer
    AS
    BEGIN
    CREATE TABLE #temp (id INT, col2 UNIQUEIDENTIFIER);
    INSERT INTO #temp VALUES(1, NEWID());
       SELECT * FROM #temp;
       EXEC [#inner];
    END
    GO
    
    CREATE PROCEDURE #inner
    AS
    BEGIN
        CREATE TABLE #temp (id INT, total INT);
        INSERT INTO #temp
        SELECT 2, 10;
    
        SELECT * FROM #temp;
    END
    GO
    
    EXEC #outer
    
      

    操作数类型碰撞:int与uniqueidentifier

    不兼容