August 3, 2009 at 12:16 pm
Hi!
I need to do a cursor that calculates the subtotal from a query with 2 subqueries. I'll return the result to Delphi. That´s my first cursor and I did it:
ALTER PROC [dbo].[FluxoContas]
@DT_START AS DATE,
@DT_END AS DATE,
@DT_START AS DATE,
@DT_END AS DATE
AS
DECLARE @COD AS INTEGER
DECLARE @MYDATE AS DATE
DECLARE @RECEIVE AS FLOAT
DECLARE @PAY AS FLOAT
DECLARE @PEOPLE AS NVARCHAR(40)
DECLARE @KIND AS CHAR(1)
DECLARE @RESULT AS FLOAT
DECLARE MyCursor SCROLL CURSOR
FOR
SELECT COD, MYDATE, RECEIVE, PAY, PEOPLE, KIND FROM (
SELECT C.COD,
C.DATA_VENCTO AS MYDATE,
0 AS RECEIVE,
C.VALOR_NOMINAL AS PAY,
F.FORNECEDOR AS PEOPLE,
'P' AS KIND
FROM ACCOUNTS_PAY C, SUPPLYERS F
WHERE C.FORNECEDOR = F.CODIGO
UNION
SELECT C.COD,
C.DATA_VENCTO AS MYDATE,
C.VALOR_NOMINAL AS RECEIVE,
0 AS PAY,
'MENSALIDADE' AS PEOPLE,
'R' AS KIND
FROM ACCOUNTS_RECEIVE C
)
ACCOUNTS_TEMP
ORDER BY 2, 1
CREATE TABLE #MY_TEMP (COD BIGINT, MYDATE DATE, RECEIVE FLOAT,
PAY FLOAT, PEOPLE NVARCHAR(40), KIND CHAR(1), RESULT FLOAT)
OPEN MyCursor
FETCH NEXT FROM MyCursor INTO @COD , @MYDATE , @RECEIVE , @PAY , @PEOPLE , @KIND
WHILE @@FETCH_STATUS = 0
BEGIN
@RESULT= @RESULT + @RECEIVE - @PAY
INSERT INTO #TEMPORARIA VALUES (@COD , @MYDATE , @RECEIVE , @PAY , @PEOPLE , @KIND , @RESULT)
FETCH NEXT FROM MyCursor INTO @COD , @MYDATE , @RECEIVE , @PAY , @PEOPLE , @KIND
END
CLOSE MyCursor
DEALLOCATE MyCursor
When I compile it tells me that the line:
@RESULT= @RESULT + @RECEIVE - @PAY
Is wrong. @RESULT is not recognized.
I need to to this operation and return #MY_TEMP as result.
How do I do this?
August 4, 2009 at 8:22 am
SET @RESULT= @RESULT + @RECEIVE - @PAY
-- Gianluca Sartori
August 4, 2009 at 8:24 am
I also suggest not to use cursors: they're slow.
There's almost nothing that can't be done without cursors.
-- Gianluca Sartori
August 4, 2009 at 8:47 am
Thanks!!!
It works fine!
But, one more question: If cursors aren´t the best choice, is there another way to do this? I don´t wanna do this operation in a external software, I need to do this operation direct into SQL Server. Is it possible?
August 4, 2009 at 9:21 am
You could use the famous "quirky update" algorithm by Jeff Moden.
It is described in an article that is currently under construction. I hope it will be soon fixed. The link is here:
http://www.sqlservercentral.com/articles/Advanced+Querying/61716/
Anyway, even if the article is in process of rewrite, you can still rely on the technique.
For your tables this should do the trick. I'm not 100% sure that it will work because I had no sample data to test it: if it doesn't work and you want to go this way, you can post here sample data and DDL for your tables.
ALTER PROC [dbo].[FluxoContas]
@DT_START AS DATE,
@DT_END AS DATE,
@DT_START AS DATE,
@DT_END AS DATE
AS
DECLARE @COD AS INTEGER
DECLARE @MYDATE AS DATE
DECLARE @RESULT AS FLOAT
CREATE TABLE #MY_TEMP
(
COD BIGINT,
MYDATE DATE,
RECEIVE FLOAT,
PAY FLOAT,
PEOPLE NVARCHAR(40),
KIND CHAR(1),
RESULT FLOAT
)
CREATE CLUSTERED INDEX IX_TMP_ORDERBY --clustered to resolve "Merry-go-Round"
ON #MY_TEMP (COD, MYDATE)
INSERT INTO #MY_TEMP
SELECT C.COD,
C.DATA_VENCTO AS MYDATE,
0 AS RECEIVE,
C.VALOR_NOMINAL AS PAY,
F.FORNECEDOR AS PEOPLE,
'P' AS KIND,
CAST(0 AS float) AS Result
FROM ACCOUNTS_PAY C,
SUPPLYERS F
WHERE C.FORNECEDOR = F.CODIGO
UNION
SELECT C.COD,
C.DATA_VENCTO AS MYDATE,
C.VALOR_NOMINAL AS RECEIVE,
0 AS PAY,
'MENSALIDADE' AS PEOPLE,
'R' AS KIND,
CAST(0 AS float) AS Result
FROM ACCOUNTS_RECEIVE C
ORDER BY 2, 1
UPDATE #My_Temp
SET @Result = Result = @RESULT + @RECEIVE - @PAY
FROM #My_Temp WITH (INDEX(IX_TMP_ORDERBY),TABLOCKX)
SELECT *
FROM #My_temp
Hope this helps
Gianluca
-- Gianluca Sartori
August 4, 2009 at 10:21 am
Hi, thanks for helping!
This code will process each row using @RESULT from one line to another?
I need take the @RESULT from atual row and use it on the next row... @RESULT has a accumulated value since first row until last... this is a money account operation.
August 4, 2009 at 9:41 pm
willian (8/4/2009)
Hi, thanks for helping!This code will process each row using @RESULT from one line to another?
I need take the @RESULT from atual row and use it on the next row... @RESULT has a accumulated value since first row until last... this is a money account operation.
Absolutely... and it's capable of doing a million rows in under 7 seconds.
--Jeff Moden
Change is inevitable... Change for the better is not.
August 4, 2009 at 9:46 pm
Just don't get the idea that you can use any ol' index to do this... It MUST be a clustered index.
--Jeff Moden
Change is inevitable... Change for the better is not.
August 4, 2009 at 11:01 pm
I may have missed it, but you will want to ensure that @RESULT is initialized to zero (0) before you start the update.
August 5, 2009 at 1:15 am
Hi Jeff, thanks for chiming in!
When will the article be online again? It's hard to explain this technique to others without the help of your article... expecially for poor pretenders like me! 🙂
-- Gianluca Sartori
August 5, 2009 at 9:35 am
Gianluca Sartori (8/5/2009)
Hi Jeff, thanks for chiming in!When will the article be online again? It's hard to explain this technique to others without the help of your article... expecially for poor pretenders like me! 🙂
You're definitely not a pretender, Gianluca. You're becoming one of the greats on this forum.
I thought I could get back to the article a couple of times and just haven't been able to do it. I may have to split it in two so I can get it done. I don't have a hard date yet. Apologies for the slothfulness on this one. I'm so far behind that I need to be twins to catch up. Like I said to a friend the other day, "It's no longer a matter of how many sticks I have in the fire, it's now a matter of how fires I have sticks in.". 😛
--Jeff Moden
Change is inevitable... Change for the better is not.
August 6, 2009 at 6:53 am
I'm a bit curious... what was the issue? I know that you can't do a "top 100 per cent" ... "order by ..." statement in a view... is this the same issue?
If so... does the OVER statement work at all?
i.e.
create view guaranteedOrderView
select xxx, row_number() over (order by xxx) as OrderNo
Not sure how to test it to see for myself...
August 6, 2009 at 7:18 am
Lynn Pettis (8/4/2009)
I may have missed it, but you will want to ensure that @RESULT is initialized to zero (0) before you start the update.
How would you initiliaze the @result to zero (0) ?
--
:hehe:
August 6, 2009 at 7:24 am
August 6, 2009 at 7:30 am
ta.bu.shi.da.yu (8/6/2009)
Slick84 (8/6/2009)
Lynn Pettis (8/4/2009)
I may have missed it, but you will want to ensure that @RESULT is initialized to zero (0) before you start the update.How would you initiliaze the @result to zero (0) ?
set @result=0.0
So not trying to hi-jack this thread but If i'm doing multiple inserts/updates in a stored procedure and storing the counts after each update/insert in a variable and then passing the value onto another stored procedure, do I have to initialize it to zero (0) before it gets to the next statement or does it automatically initialize to zero(0) after i've passed the parameter?
Like so...
update1
set @value = @@rowcount
exec dbo.storedprocedure @value
update2
set @value = @@rowcount
exec dbo.storedprocedure @value
insert1
set @value = @@rowcount
exec dbo.storedprocedure @value
insert2
set @value = @@rowcount
exec dbo.storedprocedure @value
insert3
set @value = @@rowcount
exec dbo.storedprocedure @value
update3
set @value = @@rowcount
exec dbo.storedprocedure @value
And so on...
--
:hehe:
Viewing 15 posts - 1 through 15 (of 22 total)
You must be logged in to reply to this topic. Login to reply