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.

 All Forums
 SQL Server 2000 Forums
 Transact-SQL (2000)
 Temporary Table using T-SQL...

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 Optimizer
TG
Go to Top of Page

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)
Go to Top of Page

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 y
from (
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
) a
group by [id]

EDIT:
output of source:
id xy val
----------- ---- -----------
1 x 10
1 y 100
2 x 20
2 y 200


output of results
id x y
----------- ----------- -----------
1 10 100
2 20 200



Be One with the Optimizer
TG
Go to Top of Page

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 solution

steve

-----------

Oh, so they have internet on computers now!
Go to Top of Page

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.2324
2 32432.324324
3 32424.324324
4 324324.324324


where 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
AS
DECLARE @temptable TABLE
(position int, vertices float)

DECLARE @i int, @tableSize int, @xVert float, @yVert float

--index value
SET @i = 1

--call cvs to list function and save returned table in to tempTable
INSERT @tempTable(position, vertices)
SELECT position, vertices
FROM dbo.cvs_to_table(@XYcvs)
--iterate through each row and retrieve the corresponding values
WHILE @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
Go to Top of Page

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 solution

steve

-----------

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).
Go to Top of Page

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 on
declare @src table ([position] int, vertices numeric(15,6))
insert @src
select 1, 32443.2324 union all
select 2, 32432.324324 union all
select 3, 32424.324324 union all
select 4, 324324.324324

select x.vertices as x
,y.vertices as y
from @src x
join @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 numbers
order by x.position

output:
x y
----------------- -----------------
32443.232400 32432.324324
32424.324324 324324.324324


Be One with the Optimizer
TG
Go to Top of Page

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
Go to Top of Page

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 returned

xPosition yPosition xVertices yVertices
----------- ----------- ----------------- -----------------
1 2 32443.232400 32432.324324
2 3 32432.324324 32424.324324
3 4 32424.324324 324324.324324
4 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 Optimizer
TG
Go to Top of Page

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 <= @cnt

this 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 on
go

declare @xytable table (position int, vertices float)
declare @i int
,@x float
,@y float
,@id int
,@cnt int
,@s datetime

set @i = 1
while @i < 5000
begin
insert @xytable
values (@i, @i*100)
set @i = @i+ 1
end

select @i = 1
,@cnt = (SELECT count(position) FROM @XYTable)

set @s = getdate()
--WHILE @i <= (SELECT count(position) FROM @XYTable)
while @i <= @cnt
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
select datediff(millisecond, @s, getdate()) as milliseconds_ToLoop

truncate table #job

set @s = getdate()
insert #job
select x.position
,x.vertices as x
,y.vertices as y
from @xytable x
join @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 numbers
order by x.position

select datediff(millisecond, @s, getdate()) milliseconds_SetBased
drop table #job


milliseconds_ToLoop
-------------------
3466

milliseconds_SetBased
---------------------
46


Be One with the Optimizer
TG
Go to Top of Page

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
Go to Top of Page
   

- Advertisement -