有谁遇到过这样的T-SQL问题么?(100分)

O

onedot

Unregistered / Unconfirmed
GUEST, unregistred user!
例如表A,B
A有字段NAME,CODELIST
A1 0
A2 0
A3 0


B有字段NAME,CODE
A1 1
A1 2
A2 1
A3 1
A3 3

我期望一个UPDATE语句后A的结果是自己当前字段的值加上从B中查询对应的CODE做串接

A NAME CODELIST
A1 012
A2 01
A3 013


我原来是用游标来做的,发现数据量大后速度有点慢。后来我改成一个SQL语句来达到目的
速度虽然快了,但是不对。它对NAME字段相同的数据仅仅更新一次。

我的SQL:
update a
set codelist=isnull(codelist,'')+b.code
from a,b
where a.name=b.name

这样的结果却是每次CODELIST只串接一次从B查询对应的CODE
A NAME CODELIST
A1 01
A2 01
A3 01

在此问问大侠不用游标直接用T-SQL可以实现我的功能需求吗?

万分感谢!

此外直接游标定义内做UPDATE操作和先定义游标然后使用?
UPDATE WHERE CURRENT OF{ { [ GLOBAL ] cursor_name } | cursor_variable_name }
哪个效率更好还是一样? 我个人测试是后者,但不知道是否有理论上的支持。
 
恐怕不能
 
---TEST DATA
SET NOCOUNT ON

DECLARE @A TABLE (NAME VARCHAR(30),CODELIST VARCHAR(10))
INSERT INTO @A VALUES ('A1','0')
INSERT INTO @A VALUES ('A2','0')
INSERT INTO @A VALUES ('A3','0')
DECLARE @B TABLE (NAME VARCHAR(30),CODE VARCHAR(10))
INSERT INTO @B VALUES ('A1','1')
INSERT INTO @B VALUES ('A1','2')
INSERT INTO @B VALUES ('A2','1')
INSERT INTO @B VALUES ('A3','1')
INSERT INTO @B VALUES ('A3','3')
-----------------------------------------------------
SELECT a.name,a.codelist,b.code,CONVERT(VARCHAR(8000),'') AS R
INTO #abc
FROM @a a JOIN @b b
ON a.NAME=b.NAME

DECLARE @R VARCHAR(8000),
@N VARCHAR(30)
SELECT @R='',@N=''
-----------------------------------------------------
UPDATE #abc
SET @R=CASE WHEN @N=Name THEN @R+CODE ELSE CodeList+Code END,
@N=CASE WHEN @N=Name THEN @N ELSE Name END,
R=@R
-----------------------------------------------------
UPDATE a
SET CodeLIST=tmp.R
FROM @A a JOIN
(
SELECT NAME,MAX(R) AS R
FROM #abc
GROUP BY NAME
)AS tmp
ON a.Name=tmp.Name
SELECT * FROM @a

DROP TABLE #abc
--------------------------------------------------------------------
create function getstr(@a varchar(20))
returns varchar(100)
as
begin
declare @b varchar(100)
set @b=''
select @b=@b+CODE from B where name=@a
return @b
end

语句:
update a
set codelist=isnull(codelist,'')+getstr(name)
---------------------------------------------------------
我会做大数据量测试做最终结果
 
我使用了17000多条B表数据作为测试,其中A表是200个NAME。两个表都没有建立任何索引。以下是测试结果

游标罚:50秒以上。。。我没耐心等下去了,所以确定不知。虽然该方法有通过建立索引达到提高效率的可能性,但只是每次UPDATE时间提高,但瓶颈在于游标移动,因此提高效率不够。

使用临时表方法:8-9秒。该方法速度还可以。但显然大家都看到了瓶颈在于临时表的创建和COPY数据,以及额外的对临时表本身的一次UPDATE。这些都浪费了时间。但这种方法还没有办法,因为针对B表排序后结果插入到临时表还必须要。该方法如果建立索引合适也提高效率,但同样不多,因为只有最后一次对A的UPDATE才有点作用。临时表本身的消耗依旧。

用自定义函数的方法:3-4秒。而且该方法里函数体内的语句效率和B表索引关系密切,如果索引建立好,效率会更高,而整个UPDATE的效率也自然高。
 
顶部