Sql 随附条款执行令

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

在一个简化的场景中,我有一个表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


在没有其他临时表的情况下解决这个问题有什么想法吗?

一种方法是使用临时表。您无法控制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的表。