Sql 随附条款执行令
在一个简化的场景中,我有一个表T,看起来像:Sql 随附条款执行令,sql,sql-server,Sql,Sql Server,在一个简化的场景中,我有一个表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 ( S
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
在没有其他临时表的情况下解决这个问题有什么想法吗?一种方法是使用临时表。您无法控制SQLServer决定如何优化其查询 如果不需要临时表,可以执行两个更新:
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;
您可以这样尝试:
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;
是否有另一列可用于区分
1 NULL
行(等)?Value
总是NULL
开始吗?@AakashM好吧,我可以从每一行的NULL开始,我知道Foo(Key)总是不同于NULL,如果我明白你的意思,为什么要避免临时表?@NenadZivkovic和我现在想问的问题完全一样:-)我考虑过这个选项,但是我更喜欢避免使用临时表(正如我在问题中所说的)@willy好的,对声明的表变量怎么办?我编辑了我的答案以反映这种方法。现在唯一的临时表是我定义用来创建测试sceanrio的表。