Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
| Author |
Topic |
|
manny
Starting Member
14 Posts |
Posted - 2006-02-19 : 14:04:40
|
| I have a function which returns a table, is there any way I can store this table temporarily in memory so I can loop through the different values? |
|
|
TG
Master Smack Fu Yak Hacker
6065 Posts |
Posted - 2006-02-19 : 14:40:32
|
| Yes, but what are you going to do for each loop itteration? You can probably (and should) perform the work against the entire set of rows returned by your function at once rather than 1 at a time with a loop .but to answer your question, two possibilities for storing data temporarily are:A temp table which is an actual table stored in tempdb. To create his type of temp table just create a table where the name is prepended with a hash (#) character. ie: #temp1. This table will be automagically dropped by sql server when the session using it is killed.The other way is to use a table variable. ie:declare @tblVar TABLE (<column Definition>) . There are advanatages and disadvantages to both structures. But again, usually whatever a developer new to Sql Server wants to do with a loop usually should be accomplished as a set.Be One with the OptimizerTG |
 |
|
|
manny
Starting Member
14 Posts |
Posted - 2006-02-19 : 14:59:25
|
| thanks for thw quick reply. I want to iterate through the table as I want to extract every two values and insert them in to two column in to another table. i.e. currently it returnd sa table tableXY(listPosition, coords) - where the coords alternate between x and y. i.e. the first tuple is x, the second tuple is y, the 3rd tuple is x, the fourth tuple is y etc. I want to extract eaxh x and y valuye and insert it in to another table where the structure is coordinates(ID, x, y) (i was forced to use this hideous way of programming it, as it could'nt think of any other soloution as the input comes in as a cvs list)p.s any ideas why this returns a syntax error:WHILE (@i <= SELECT count(listPosition) FROM tableXY) |
 |
|
|
TG
Master Smack Fu Yak Hacker
6065 Posts |
Posted - 2006-02-19 : 15:34:17
|
This will prevent the syntax error:WHILE @i <= (SELECT count(listPosition) FROM tableXY)If you post the structure of your source result set, me or someone may be able to offer a "set based" solution. Here is a possible way of grabbing alternate values as x/y pairs:select [id] ,sum(x) as x ,sum(y) as yfrom ( select [id] ,x = case when xy = 'x' then val else 0 end ,y = case when xy = 'y' then val else 0 end from (--Your source result set select 1 as [id], 'x' as xy, 10 as val union select 1, 'y', 100 union all select 2, 'x', 20 union all select 2, 'y', 200 ) a ) agroup by [id]EDIT:output of source:id xy val ----------- ---- ----------- 1 x 101 y 1002 x 202 y 200output of resultsid x y ----------- ----------- ----------- 1 10 1002 20 200 Be One with the OptimizerTG |
 |
|
|
elwoos
Master Smack Fu Yak Hacker
2052 Posts |
Posted - 2006-02-20 : 03:55:00
|
quote: tableXY(listPosition, coords) - where the coords alternate between x and y. i.e. the first tuple is x, the second tuple is y, the 3rd tuple is x, the fourth tuple is y etc
This is a very high risk assumption to make as the order is not guaranteed. TG is right you need to post your source structure then someone can help you come up with a better solutionsteve-----------Oh, so they have internet on computers now! |
 |
|
|
manny
Starting Member
14 Posts |
Posted - 2006-02-20 : 09:02:00
|
| I've renamed the variables hoping it is'nt detected during my departments rather extensive plagiarism checks. It being my final year university project, the last thing I want to get done for is plagiarism or any other forms of "cheating".The table I'm trying to populate is:vertices(ID, x, y)The input value is simply a cvs list of float values of variable length i.e. 32443.2324,32432.324324,32424.324324,324324.324324 where I'm saying (but have'nt explicitly coded) that the the values alternate between x and y values (delimitted by the comma). The cvs_to_table function works fine and it returns a table XYTable(position,vertices)therefore for the example above it would return:position vertices--------- --------1 32443.23242 32432.3243243 32424.3243244 324324.324324where position is the index of its position in the list. I think my rather badly written code below portrays a sense of what I'm trying to achieve (its throwing errors which state that tempXY is'nt recognised in both of the select statements in the while loop.)ALTER PROCEDURE addvertices @ID int, @XYcvs ntext ASDECLARE @temptable TABLE (position int, vertices float)DECLARE @i int, @tableSize int, @xVert float, @yVert float--index valueSET @i = 1--call cvs to list function and save returned table in to tempTableINSERT @tempTable(position, vertices)SELECT position, vertices FROM dbo.cvs_to_table(@XYcvs)--iterate through each row and retrieve the corresponding valuesWHILE @i <= (SELECT count(position) FROM tempTable)BEGIN SELECT xVert = vertices FROM tempTable WHERE position = @i SELECT yVert = vertices FROM tempTable WHERE position = (@i + 1)--insert x and y in to the target table INSERT INTO vertices(ID, x, y) VALUES(@ID, @xVert, @yVert) SET @i = @i + 2 END |
 |
|
|
manny
Starting Member
14 Posts |
Posted - 2006-02-20 : 09:03:09
|
quote: Originally posted by elwoos
quote: tableXY(listPosition, coords) - where the coords alternate between x and y. i.e. the first tuple is x, the second tuple is y, the 3rd tuple is x, the fourth tuple is y etc
This is a very high risk assumption to make as the order is not guaranteed. TG is right you need to post your source structure then someone can help you come up with a better solutionsteve-----------Oh, so they have internet on computers now!
The input is being set through javascript, therefore I have good control over the format its in (i think). |
 |
|
|
TG
Master Smack Fu Yak Hacker
6065 Posts |
Posted - 2006-02-20 : 10:58:13
|
Given your source here is good way to derive XY coordinates (since your function will return the csv in order). You mention this is for school. This site is really for professionals, participants are discouraged from "helping" with homework. However, it's nice to see an assignment that is a little more advanced than "show all the authors that haven't published books". Obviously it's up to your judgement as to what solution you want to turn in. If the assignment was geared towards looping (or the prof's sql sofistication isn't too great) then the set based solution might just earn you an F. . But anyway, I hope this topic hsa been a learning experience rather than a plagiarism opportunity.set nocount ondeclare @src table ([position] int, vertices numeric(15,6))insert @srcselect 1, 32443.2324 union allselect 2, 32432.324324 union allselect 3, 32424.324324 union allselect 4, 324324.324324 select x.vertices as x ,y.vertices as yfrom @src xjoin @src y on y.position -1 = x.position --Count on Position to alternate Xs and Ys and x.position % 2 > 0 --make sure Xs are odd numbers and y.position % 2 = 0 --make sure Ys are event numbersorder by x.positionoutput:x y ----------------- ----------------- 32443.232400 32432.32432432424.324324 324324.324324 Be One with the OptimizerTG |
 |
|
|
manny
Starting Member
14 Posts |
Posted - 2006-02-20 : 14:25:39
|
| its more than "school homework", is for university and the project is on parr with systems I have worked on while based in industry. The fuction I'm stuck in is a small but plays an important role in the system.The solution provided above, I can't seem to comprehend, I understand each predicate in the join statement but how it all fits togethor I can't seem to understand.Also, can a numeric variable type store values to a higher d.p over float?Anyway, I managed to get my previous attempt up and working. Can anyone suggest any minor tweaks I can make to it to make it more efficient:WHILE @i <= (SELECT count(position) FROM @XYTable)BEGIN SELECT @x = xValue.vertices FROM @XYTable xValue WHERE xValue.position= @i SELECT @y = yValue.vertices FROM @XYTable yValue WHERE yValue.position = (@i + 1) INSERT INTO job(ID, x, y) VALUES(@ID, @x, @y) SET @i = @i + 2 END |
 |
|
|
TG
Master Smack Fu Yak Hacker
6065 Posts |
Posted - 2006-02-20 : 14:46:58
|
>>but how it all fits togethor I can't seem to understand.It's a simple inner (self) join. Joining 2 "instances" of the same table. the "y.position-1=x.position" associates the y with the previous x. The other criteria makes sure that the row (in red) are not returned. The INNER join makes sure the row (in blue) is not returnedxPosition yPosition xVertices yVertices ----------- ----------- ----------------- ----------------- 1 2 32443.232400 32432.3243242 3 32432.324324 32424.3243243 4 32424.324324 324324.3243244 NULL 324324.324324 NULL >>Also, can a numeric variable type store values to a higher d.p over float?you just have more control over precision with numeric datatype (than float)Be One with the OptimizerTG |
 |
|
|
TG
Master Smack Fu Yak Hacker
6065 Posts |
Posted - 2006-02-20 : 19:24:33
|
>>Can anyone suggest any minor tweaks I can make to it to make it more efficient:change this:WHILE @i <= (SELECT count(position) FROM @XYTable)to this:set @cnt = (SELECT count(position) FROM @XYTable)while @i <= @cntthis way you aren't getting the count for every loop. I was testing against 5000 rows in @xytable and this change dropped the exection time (in milliseconds) from 7670 to 3466.However the set based solution accomplished the same thing in 46 milliseconds. I just wanted to give you an idea of the savings from procedural based programming and set based programming in sql server. Here's the test code I used:create table #job(id int, x float, y float)set nocount ongodeclare @xytable table (position int, vertices float)declare @i int ,@x float ,@y float ,@id int ,@cnt int ,@s datetimeset @i = 1while @i < 5000begin insert @xytable values (@i, @i*100) set @i = @i+ 1endselect @i = 1 ,@cnt = (SELECT count(position) FROM @XYTable)set @s = getdate()--WHILE @i <= (SELECT count(position) FROM @XYTable)while @i <= @cntBEGIN SELECT @x = xValue.vertices FROM @XYTable xValue WHERE xValue.position= @i SELECT @y = yValue.vertices FROM @XYTable yValue WHERE yValue.position = (@i + 1) INSERT INTO #job(ID, x, y) VALUES(@ID, @x, @y) SET @i = @i + 2 ENDselect datediff(millisecond, @s, getdate()) as milliseconds_ToLooptruncate table #jobset @s = getdate()insert #jobselect x.position ,x.vertices as x ,y.vertices as yfrom @xytable xjoin @xytable y on y.position -1 = x.position --Count on Position to alternate Xs and Ys and x.position % 2 > 0 --make sure Xs are odd numbers and y.position % 2 = 0 --make sure Ys are event numbersorder by x.positionselect datediff(millisecond, @s, getdate()) milliseconds_SetBaseddrop table #jobmilliseconds_ToLoop ------------------- 3466milliseconds_SetBased --------------------- 46 Be One with the OptimizerTG |
 |
|
|
manny
Starting Member
14 Posts |
Posted - 2006-02-21 : 12:49:57
|
| the set based option does seem like the best soloution in terms of performance, for the insert verticies function I only need to insert a maximum of 20 records in to the database at a time, therefore performance under the loop should be acceptable. Thanks.Manny |
 |
|
|
|
|
|
|
|