如何用光标找到每个客户的第四个订单 [英] how to find the 4th order for each customer with cursor

查看:73
本文介绍了如何用光标找到每个客户的第四个订单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想找到每个客户的第4个订单及其所有订单之间的Title_order(按订单日期排序)。如果他们没有订单或少于4返回NULL。使用Cursor限制它。我创建了这个,但是给我回复了所有订单。

我有桌子

顾客filds fname,lname,Id_customer

订购filds ID_order,date,title_order

  ALTER   function  [dbo]。[f4order]( @ id_customer   int  @ID_order   int 
返回 varchar 255
as 开始

声明 @ row3 as int @ data as date @ 4order as varchar 50

DECLARE myCursor CURSOR FOR
选择 ID_order
来自选择 ID_order,ROW_NUMBER() over 订单 DATE desc as row 来自 订单
其中 Id_customer = @ id_customer) as tmp
其中行= 4
打开 myCu rsor;
FETCH NEXT FROM myCursor INTO @ row4
WHILE @@ FETCH_STATUS = 0
开始
if (@ row4 = @ ID_order
begin
set @ 4order =(选择编号来自 订单 其中 @ ID_order = ID_order)
结束
else
set @ 4order = ' null'

FETCH NEXT FROM myCursor INTO @ row4 ;
end

CLOSE myCursor
DEALLOCATE myCursor

return @ 4order
end
;



不知道是否可以完成



提前谢谢

解决方案

我终于得到了你的代码,一旦我得到了正确的答案修复了所有错误......

ORDER DATE 是保留字,所以如果您要将它们用作表格或列名称,则必须用方括号括起来,即 [order],[DATE] 。更好的是,选择不同的名字。您也没有声明 @ row4



在您提供的代码中,不需要游标因为你已经使用 ROW_NUMBER 意味着你可以直接定位第4行 - 这实际上就是你用

做的事情,其中​​row = 4 



注意:形成游标的查询只返回一行,因为你有 FETCH NEXT 一个 ELSE 子句。如果您打算使用光标,请确保总是获取下一行,否则您可能会无限循环。



以下简单的示例显示如何使用游标在查询中查找第4行(CAVEAT - 这不是推荐的方法,仅用于演示光标)



我设置了一些样本数据,其中包含一个数字为1到19的int和一个包含一些文本的varchar列(单词'text'后跟与id相同的数字)

< pre lang =SQL> 创建 table cursorExample

id int identity 1 1 ),
someData varchar (max)


声明 @ i int = 1
while @ i < 20
开始
insert into cursorExample values ' text' + cast( @ i as varchar ))
set @ i = @ i + 1
end



现在想象一下,我想找到该表末尾的第4行。即此查询的第4行

 选择 id,someData 来自 cursorExample 订单  id  DESC  



我可以使用以下sql

 声明  @myInt   int  
声明 @myVarchar varchar (max)

声明 @ myDesiredInt int = 4
声明 @ myFoundVarchar varchar (max)
声明 @ myFoundInt int

声明 @ loopCount int = 1

声明 myCursor cursor
选择 id,someData 来自 cursorExample order id DESC

打开 myCursor
获取下一步来自 myCursor 进入 @ myInt @ myVarChar
while @@ FETCH_STATUS = 0
begin
print cast( @ loopCount as varchar )+ ' :'
+ @ myVarChar + ' :' + cast( @myInt as varchar )+ ' :'
+ isnull(cast( @ myFoundInt as varchar ),' null')+ ' :'
+ isnull( @ myFoundVarchar ' null'

如果 @ loopCount = @ myDesiredInt
开始
set @myFoundVarchar = @ myVarchar
set @myFoundInt = @ myInt
end
set @ loopCount = @ loopCount + 1
fetch next 来自 myCursor into @ myInt , @ myVarChar
end
关闭 myCursor
deallocate myCursor
print @ myFoundVarchar
print @ myFoundInt



注意事项:

- 我正在使用 @loopcount 来计算提取的行数从光标 - 当我找到我想要的行时,我只设置输出变量。

- 我在每个循环中无条件地增加 @loccount

- 我在循环中无条件地获取光标的下一行

- 循环中那个冗长的打印语句只是为了演示正在发生的事情,即

 1:text19:19:null:null 
2:text18:18:null:null
3:text17:17:null:null
4:te xt16:16:null:null
5:text15:15:16:text16
6:text14:14:16:text16
7:text13:13:16:text16
8:text12:12:16:text16
9:text11:11:16:text16
10:text10:10:16:text16
11:text9:9:16:text16
12:text8:8:16:text16
13:text7:7:16:text16
14:text6:6:16:text16
15:text5:5:16:text16
16:text4:4:16:text16
17:text3:3:16:text16
18:text2:2:16:text16
19:text1:1:16 :text16

注意 - 因为 print 语句位于循环的开头,所以直到第5个循环才会出现所需的结果。



请注意,光标直到结束 - 这是游标提取数据的一种非常低效的方式之一。



通过引入另一个变量

  decl,可以突破游标循环是  @ abortLoop   int  =  0  

,将 WHERE 更改为

 ,而 @@ FETCH_STATUS  =  0    @ abortLoop  =  0 

并将新变量设置为另一个值找到所需的值

设置@myFoundVarchar = @myVarchar 
设置@myFoundInt = @myInt
设置@abortLoop = 1

然后输出是

  1 :text19: 19  null  null  
2 :text18: 18 null null
3 :text17: 17 null null
4 :text16: 16 null null
text16
16


I want to find the 4-th order for each customer and his Title_order (ordering by date of order) between all of its orders. If they dont have orders or have less than 4 return NULL. It's restricted using Cursor. I have created this but returns me all the order.
I have the tables
customer with filds fname, lname,Id_customer
order with filds ID_order, date, title_order

ALTER function [dbo].[f4order](@id_customer int, @ID_order int)
returns varchar (255)
as begin 

declare  @row3 as int, @data as date, @4order as varchar(50)

DECLARE myCursor CURSOR FOR
	 select ID_order
	 from (select ID_order , ROW_NUMBER() over(order by DATE desc) as row from order 
			where Id_customer=@id_customer) as tmp
			where  row=4
open myCursor;
FETCH NEXT FROM myCursor INTO @row4
WHILE @@FETCH_STATUS = 0 
	begin
	if (@row4=  @ID_order)
		begin
			set @4order= (select number from order where @ID_order=ID_order)
		end
	else 
			set @4order ='null' 
		
		FETCH NEXT FROM myCursor INTO @row4;
	end
	
CLOSE myCursor
DEALLOCATE myCursor

return @4order
end 
;


don't know if could be done

Thanks in advance

解决方案

Well I finally got your code to return the correct answer once I'd fixed all of the bugs...
ORDER and DATE are reserved words, so if you are going to use them as table or column names you must surround them with square brackets i.e. [order], [DATE]. Better still, choose different names. You also did not declare @row4.

In the code you have presented there is no need for a cursor at all because you have used ROW_NUMBER meaning you can target the 4th row directly - which is essentially what you have done with

where  row=4


NOTE: It is just as well that the query forming the cursor returns only a single row as you have the FETCH NEXT within an ELSE clause. If you are going to use a cursor then make sure you always fetch the next row otherwise you could end up in an infinite loop.

The following trivial example shows how to find the 4th row in a query using a cursor (CAVEAT - this is not a recommended approach and is used to demonstrate the cursor only)

I set up some sample data that contains an int with the numbers 1 to 19 inclusive and a varchar column that contains some text (the word 'text' followed by the same number as the id)

create table cursorExample
(
	id int identity(1,1),
	someData varchar(max)
)

declare @i int = 1
while @i < 20
begin
	insert into cursorExample values ('text' + cast(@i as varchar))
	set @i = @i + 1
end


Now imagine I want to find the 4th row from the end of that table. I.e. the 4th row of this query

select id, someData from cursorExample order by id DESC 


I can do that with the following sql

declare @myInt int
declare @myVarchar varchar(max) 

declare @myDesiredInt int = 4
declare @myFoundVarchar varchar(max)
declare @myFoundInt int

declare @loopCount int = 1

declare myCursor cursor for
	select id, someData from cursorExample order by id DESC 

open myCursor
fetch next from myCursor into @myInt, @myVarChar
while @@FETCH_STATUS = 0
begin
	print cast(@loopCount as varchar) + ' : ' 
			+ @myVarChar + ' : ' + cast(@myInt as varchar) + ' : '
			+ isnull(cast(@myFoundInt as varchar), 'null') + ' : ' 
			+ isnull(@myFoundVarchar,'null')

	if @loopCount = @myDesiredInt
	begin
		set @myFoundVarchar = @myVarchar
		set @myFoundInt = @myInt
	end 
	set @loopCount = @loopCount + 1
	fetch next from myCursor into @myInt, @myVarChar
end
close myCursor
deallocate myCursor
print @myFoundVarchar
print @myFoundInt


Points to note:
- I'm using @loopcount to count the rows fetched from the cursor - I only set the "output" variables when I find the row I want.
- I increment @loopcount unconditionally within each loop
- I fetch the next row of the cursor unconditionally within the loop
- That long-winded print statement within the loop is just to demonstrate what is going on i.e.

1 : text19 : 19 : null : null
2 : text18 : 18 : null : null
3 : text17 : 17 : null : null
4 : text16 : 16 : null : null
5 : text15 : 15 : 16 : text16
6 : text14 : 14 : 16 : text16
7 : text13 : 13 : 16 : text16
8 : text12 : 12 : 16 : text16
9 : text11 : 11 : 16 : text16
10 : text10 : 10 : 16 : text16
11 : text9 : 9 : 16 : text16
12 : text8 : 8 : 16 : text16
13 : text7 : 7 : 16 : text16
14 : text6 : 6 : 16 : text16
15 : text5 : 5 : 16 : text16
16 : text4 : 4 : 16 : text16
17 : text3 : 3 : 16 : text16
18 : text2 : 2 : 16 : text16
19 : text1 : 1 : 16 : text16

Note - because the print statement is at the start of the loop then the desired results don't start appearing until the 5th loop.

Notice that the cursor runs "until the end" - which is one of the reasons that cursors can be a very inefficient way to extract data.

It is possible to "break out" of the cursor loop by introducing another variable

declare @abortLoop int = 0

, change the WHERE to be

while (@@FETCH_STATUS = 0 and @abortLoop = 0)

and set the new variable to another value once the desired values are found

set @myFoundVarchar = @myVarchar
set @myFoundInt = @myInt
set @abortLoop = 1

The output will then be

1 : text19 : 19 : null : null
2 : text18 : 18 : null : null
3 : text17 : 17 : null : null
4 : text16 : 16 : null : null
text16
16


这篇关于如何用光标找到每个客户的第四个订单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆