您的位置:首页 > 其它

利用游标实现较复杂的多表查询

2006-04-17 01:39 471 查看
  上个星期,在实验室的时候,赵老师给我出了一道题,要求用半小时解决。可是,我却花了15分钟去回忆存储过程的格式,至于游标则早就忘到九宵云外了



  今晚重新复习了一下格式,总算把题目解决了,不过来来回回总共花了我三个小时,包括中间的QQ聊天时间,哈哈。现在把题目略述如下:

  要求在pubs数据库中,提取出每一个出版商所出版的书中,总销量最高的书的信息(书ID、书名、出版社ID、出版社名、总销量)。

  本人的解决方案如下(我没写存储过程,其实只要加一个存储过程的外壳就可以了):

[code]--author:zyk
--renew time:17/04/06 晚上0:50分

USE tempdb
IF EXISTS (SELECT * FROM sysobjects WHERE id=object_ID('#aTable') AND Xtype='U') 
 	DROP TABLE #aTable

IF EXISTS (SELECT * FROM sysobjects WHERE id=object_id('#bTable') AND Xtype='U')
 	DROP TABLE #bTable

IF EXISTS (SELECT * FROM sysobjects WHERE ID=OBJECT_ID('#cTable') AND Xtype='U')
 	DROP TABLE #cTable 
GO

USE pubs

SELECT t.title_id, t.title, p.pub_id, p.pub_name,sum(s.qty)as num
 	INTO #aTable
 	FROM titles t INNER JOIN publishers p
	 ON t.pub_id = p.pub_id INNER JOIN sales s
	 ON s.title_id = t.title_id
	 GROUP BY t.title_id,t.title,p.pub_id,p.pub_name
GO
SELECT * FROM #aTable

SELECT pub_id 
 	INTO #cTable
	FROM #aTable
 	GROUP BY pub_id
GO
--创建一个列属性与#aTable相同的空表#bTable
SELECT * INTO #bTable FROM #aTable

GO

------------------------------------------
SET NOCOUNT ON
DELETE #bTable
DECLARE 	@old_title_id varchar(6),
	@cur_title_id char(6),
 	@old_title varchar(80),
	@cur_title varchar(80),
 	@old_pub_id  char(4),
 	@cur_pub_id  char(4),
 	@old_pub_name varchar(40),
 	@cur_pub_name varchar(40),
 	@old_num smallint,
 	@cur_num smallint,
 	@I  INT

--定义游标secCursor
DECLARE secCursor CURSOR FOR
SELECT pub_id FROM #cTable 
 
--打开游标secCursor
OPEN secCursor

--初始化循环变量@I
SELECT @I = (SELECT COUNT(*) FROM #cTable)

--逐条读取
WHILE @I != 0
BEGIN
	FETCH NEXT FROM secCursor INTO @cur_pub_id

--定义嵌套的游标myCursor
 	DECLARE myCursor CURSOR FOR
 	SELECT title_id, title, pub_id, pub_name, num FROM #aTable

--打开游标myCursor
 	OPEN myCursor
 
	--逐条读取
 	WHILE (SELECT COUNT(*) FROM #cTable)>0
 	BEGIN
  		FETCH NEXT FROM myCursor INTO @old_title_id, @old_title, @old_pub_id,

  @old_pub_name, @old_num
  		IF @cur_pub_id = @old_pub_id BREAK --跳出无限循环
 	END
 	--@@FETCH_STATUS = 0 则读取成功
 	WHILE @@FETCH_STATUS = 0
  	BEGIN
   		FETCH NEXT FROM myCursor INTO @cur_title_id, @cur_title, @cur_pub_id,

@cur_pub_name, @cur_num
   		IF @old_pub_id = @cur_pub_id AND @old_num < @cur_num
   		BEGIN
    			SELECT @old_title_id = @cur_title_id,@old_title = @cur_title,

@old_num = @cur_num

--此条语法可以加快速度.

    			DELETE  FROM #aTable WHERE CURRENT OF myCursor     
		END  
     
  	END

--把每个出版商的最大销售量的书信息写入临时表#bTable
 	INSERT  INTO #bTable(title_id, title, pub_id, pub_name, num)
  		VALUES (
   			@old_title_id,
   			@old_title,
   			@old_pub_id,
   			@old_pub_name,
   			@old_num
   		        )
	--关闭游标
	CLOSE myCursor
	--释放游标
	DEALLOCATE myCursor
	SELECT @I = @I-1
END

--关闭游标
CLOSE secCursor
--释放游标
DEALLOCATE secCursor
GO

SELECT * FROM #cTable
SELECT * FROM #bTable
GO

[/code]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: