在一个简化的场景中,我的表格 T 看起来像:
Key Value
1 NULL
1 NULL
1 NULL
2 NULL
2 NULL
3 NULL
3 NULL
我还有一个非常耗时的功能 Foo(Key),必须将其视为黑盒子(我必须使用它,我无法更改它)。
我想更新表格 T ,但要比
更有效UPDATE T SET Value = dbo.Foo(Key)
基本上我只会为每个键执行 Foo 一次。
我试过像
这样的东西WITH Tmp1 AS
(
SELECT DISTINCT Key FROM T
)
, Tmp2 AS
(
SELECT Key, Foo(Key) Value FROM Tmp1
)
UPDATE T
SET T.Value = Tmp2.Value
FROM T JOIN Tmp2 ON T.Key = Tmp2.Key
但意外的是计算时间根本没有变化,因为Sql Server似乎在每一行都再次运行 Foo 。
有没有其他临时表解决这个问题的想法?
答案 0 :(得分:2)
一种方法是使用临时表。您无法控制SQL Server如何优化其查询。
如果您不想要临时表,可以进行两次更新:
with toupdate as (
select t.*, row_number() over (partition by id order by id) as seqnum
from t
)
update toupdate
set value = db.foo(key)
where seqnum = 1;
然后您可以再次运行类似的更新:
with toupdate as (
select t.*, max(value) over (partition by id) as as keyvalue
from t
)
update toupdate
set value = keyvalue
where value is null;
答案 1 :(得分:0)
您可以这样尝试:
CREATE FUNCTION dbo.Foo(@TheKey INT)
RETURNS INT
AS
BEGIN
RETURN (SELECT @TheKey*2);
END
GO
CREATE TABLE #tbl(MyKey INT,MyValue INT);
INSERT INTO #tbl(MyKey) VALUES(1),(1),(1),(2),(2),(3),(3),(3);
SELECT * FROM #tbl;
DECLARE @tbl2 TABLE(MyKey INT,TheFooValue INT);
WITH DistinctKeys AS
(
SELECT DISTINCT MyKey FROM #tbl
)
INSERT INTO @tbl2
SELECT MyKey,dbo.Foo(MyKey) TheFooValue
FROM DistinctKeys;
UPDATE #tbl SET MyValue=TheFooValue
FROM #tbl
INNER JOIN @tbl2 AS tbl2 ON #tbl.MyKey=tbl2.MyKey;
SELECT * FROM @tbl2;
SELECT * FROM #tbl;
GO
DROP TABLE #tbl;
DROP FUNCTION dbo.Foo;