对 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.
要解决您的问题,您可以:
- 使用不同的名称以避免冲突
就在你可以之前(如果没有在嵌套过程中使用):
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'.
最有趣的是,当您使用具有相同列数(或默认值)的本地临时 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
以及类型不兼容的示例:
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
我有一个 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.
要解决您的问题,您可以:
- 使用不同的名称以避免冲突
就在你可以之前(如果没有在嵌套过程中使用):
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'.
最有趣的是,当您使用具有相同列数(或默认值)的本地临时 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
以及类型不兼容的示例:
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