对 SQL 求和而不分组或排序

Sum Over SQL without grouping or ordering

我有一个 SQL 服务器查询是这样的:

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
Invalid column name 'Total'.

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

请注意

SELECT 语句在未放在 INSERT.

之后时继续运行

没有插入的结果

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

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

要排除故障,您应该始终在插入之前检查元数据(列名):

SELECT *
FROM ##Temp
WHERE 1=2;

然后您可以很容易地发现它与您假设的不同。

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

要解决您的问题,您可以:

  1. 使用不同的名称以避免冲突
  2. 就在你可以之前(如果没有在嵌套过程中使用):

    IF OBJECT_ID('tempdb..##temp') IS NOT NULL     
    DROP TABLE ##temp
    
    CREATE TABLE ##temp...
    

还有一个令人讨厌的情况,存储过程调用另一个存储过程并且两者(外部和内部)创建具有相同名称的临时文件 table。你应该避免它。

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

最有趣的是,当您使用具有相同列数(或默认值)的本地临时 tables 并且可以进行隐式转换时,它将通过:

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

Operand type clash: int is incompatible with uniqueidentifier