May 8, 2007 at 11:32 am
Hello,
I have something to accomplish on SQL Server 2000. Say i have the following table that traces how often something is transferred:
A | B
1 | 2
2 | 3
5 | 7
7 | 8
8 | 9
9 | 10
Basically, the item starting out labeled as 1 in column A has been transferred twice ( 1 -> 2, 2 -> 3), and the one labeled as 5 has been transferred four times ( 5 -> 7, 7 -> 8, 8 -> 9, 9 -> 10). Id like to be able to generate a report something like the following:
Item #times transferred
1 2
5 4
I'm not interested in the intermediary states ( where A is 7, 8, or 9), and there won't be any times where there is a record in column A without a corresponding record in column B.
Any ideas if/how this can be done in a set-based query instead of a cursor (or loop)?
TIA, Chris.
May 8, 2007 at 12:15 pm
SELECT [A],
INTO [#Temp1]
FROM
(
SELECT 1 AS [A], 2 AS
UNION
SELECT 2 AS [A], 3 AS
UNION
SELECT 5 AS [A], 7 AS
UNION
SELECT 7 AS [A], 8 AS
UNION
SELECT 8 AS [A], 9 AS
UNION
SELECT 9 AS [A], 10 AS
) [Vals]
SELECT
[A],
,
1 AS [Transfer_Count]
INTO [#Temp2]
FROM[#Temp1] [Temp1_1]
WHERENOT EXISTS
(
SELECT *
FROM[#Temp1] [Temp1_2]
WHERE[Temp1_1].[A] = [Temp1_2].
)
WHILE @@ROWCOUNT > 0
BEGIN
UPDATE [#Temp2]
SET
= #Temp1.,
[Transfer_Count] = [Transfer_Count] + 1
FROM[#Temp2]
INNER JOIN[#Temp1]
ON[#Temp1].[A] = [#Temp2].
END
SELECT * FROM #Temp2
DROP TABLE #Temp1
DROP TABLE #Temp2
May 8, 2007 at 12:29 pm
Again the premise is not to loop the above is "looping"
I don't think there is an efficient way of solving this problem SET-BASED superior to a cursor.
Cheers,
* Noel
May 8, 2007 at 1:47 pm
Loop != Cursor
If you wanted to do this in a single select query, you would have to anticipate the maximum "times transferred" and use that many left joins - 1, which isn't practical.
If you want to join to this result set, you may want to look at making a function that returns a table.
May 8, 2007 at 1:54 pm
Kevin's solution works for me. I was stuck thinking about CUBE or ROLLUP or something else to avoid a cursor. Updates on a temp table didn't occur to me.
Thanks!
May 8, 2007 at 2:08 pm
It was a fun one to bend my mind around to clear my head of my current problems. Take it easy.
May 8, 2007 at 6:41 pm
ChrisMoix,
how do you know that item transferred from 7 to 8 is the same item transferred from 5 to 7?
How you gonna distinguish 2 deliveries from 7 to 8 happened in, say, 2 weeks one after another? Which one you're gonna count?
If you would have some ItemID in this table you'd avoid any kind of looping at all.
Just
SELECT COUNT(*), ItemID
...
GROUP BY ItemID
and that's it.
_____________
Code for TallyGenerator
May 9, 2007 at 12:29 pm
You just nailed it. It is a very poor design. But those are the requests we get most of the time.
* Noel
May 10, 2007 at 6:50 am
This is of course assuming there are no possible cycles in the table:
ie the route was: 1 -> 2 -> 3 -> 2 -> 4
Otherwise you're going to get an infinite loop.
Viewing 9 posts - 1 through 8 (of 8 total)
You must be logged in to reply to this topic. Login to reply