Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Looping thru a recordset in T-SQL

Status
Not open for further replies.

wbodger

Programmer
Apr 23, 2007
769
US
OK, I started this problem last week going down a different road. Now I have two views, one with all of the data that I need including a rowID

Code:
RowID	study_participant_id	proc_labs_psa_date	proc_labs_psa_value	Phase	inidate
1	08800021	2008-07-02 00:00:00.000	1.44	BLN	2013-01-22 09:24:02.183
2	08800021	2008-10-13 00:00:00.000	1.30	BLN	2013-01-22 09:24:02.183
3	08800021	2009-02-09 00:00:00.000	1.20	FU	2013-01-22 09:24:02.183
4	08800021	2009-04-01 00:00:00.000	1.40	FU	2013-01-22 09:24:02.183
5	08800021	2009-07-01 00:00:00.000	1.43	FU	2013-01-22 09:24:02.183
6	08800021	2009-10-14 00:00:00.000	1.33	FU	2013-01-22 09:24:02.183
7	08800021	2009-12-15 00:00:00.000	2.01	FU	2013-01-22 09:24:02.183
8	08800021	2010-04-05 00:00:00.000	5.30	FU	2013-01-22 09:24:02.183
9	08800021	2010-07-05 00:00:00.000	1.60	FU	2013-01-22 09:24:02.183
10	08800021	2010-09-24 00:00:00.000	1.50	FU	2013-01-22 09:24:02.183
11	08800021	2010-12-29 00:00:00.000	1.40	FU	2013-01-22 09:24:02.183
12	08800021	2011-04-14 00:00:00.000	1.80	FU	2013-01-22 09:24:02.183
13	08800021	2011-06-24 00:00:00.000	1.60	FU	2013-01-22 09:24:02.183
14	08800021	2011-09-28 00:00:00.000	1.30	FU	2013-01-22 09:24:02.183
15	08800021	2011-12-16 00:00:00.000	1.90	FU	2013-01-22 09:24:02.183
16	08800021	2012-04-13 00:00:00.000	1.90	FU	2013-01-22 09:24:02.183
17	08800021	2012-08-08 00:00:00.000	1.90	FU	2013-01-22 09:24:02.183
[/code

and another that whittles this down to give me that ranges that I need

[code]
newrowid	Study_Participant_ID	highrow	lowrow
1	08800021	6	1
2	08800021	7	1
3	08800021	8	1
4	08800021	9	2
5	08800021	10	2
6	08800021	11	3
7	08800021	12	5
8	08800021	13	5
9	08800021	14	6
10	08800021	15	8
11	08800021	16	9
12	08800021	17	10
(Both of these views have many more rows, I have just shown the data for the first study_participant_id.)

Now I want to use the range and study_participant_id from the second view to get the PSA_Values from the first view. I
have tried variations on

Code:
DECLARE @newid int, @intRowCount int, @spid int, @hr int, @lr int
SELECT @newid = -1,  -- Smaller value than any real data
       @intRowCount = 1 -- Force first iteration
WHILE @intRowCount >= 1
BEGIN
    SELECT @newid = MIN(newrowid)
			,@spid=[Study_Participant_ID]
			,@hr=[highrow]
			,@lr=[lowrow]
	FROM   [dbEDRN195].[dbo].[PSALimits]
    WHERE  newrowid > @newid
	group by Study_Participant_ID, highrow, lowrow
    SELECT @intRowCount = @@ROWCOUNT

    IF @intRowCount >= 1
    BEGIN
	select * from dbEDRN195.dbo.PSADates_Values
	where study_participant_id=@spid
	and RowID >= @lr and RowID<=@hr
    END
END

and

Code:
declare @newid int
declare @spid int
declare @hr int
declare @lr int

SELECT @newid=MIN(newrowid)
	   ,@spid=[Study_Participant_ID]
       ,@hr=[highrow]
       ,@lr=[lowrow]
  FROM [dbEDRN195].[dbo].[PSALimits]
  group by Study_Participant_ID, highrow, lowrow
  
print @newid
print @hr
print @lr
  
WHILE @newid is not null
begin
	select * from dbEDRN195.dbo.PSADates_Values
	where study_participant_id=@spid
	and RowID >= @lr and RowID<=@hr
	select @newid=MIN(newrowid) from dbEDRN195.dbo.psalimits where newrowid>@newid
end

but these both give me only the last record in the view. It is correct, but it is the last record and I want to get all of the sets. Below is teh output for both of these last two queries

Code:
RowID	study_participant_id	proc_labs_psa_date	proc_labs_psa_value	Phase	inidate
10	54500442	2010-10-11 00:00:00.000	7.70	BLN	2013-01-22 09:31:02.833
11	54500442	2011-05-16 00:00:00.000	8.90	BLN	2013-01-22 09:31:02.833
12	54500442	2011-08-22 00:00:00.000	8.00	BLN	2013-01-22 09:31:02.833
13	54500442	2012-02-10 00:00:00.000	8.05	BLN	2013-01-22 09:31:02.833
14	54500442	2012-08-16 00:00:00.000	9.90	BLN	2013-01-22 09:31:02.833
 
I apologize, but I still don't "get it".

Regardless, I have a query that I would like you to try. I think it might return the data you are looking for.

Code:
Select *
From   ViewNumber1
       Inner Join ViewNumber2
         On ViewNumber1.study_participant_id = ViewNumber2.study_participant_id
         And ViewNumber1.RowId Between ViewNumber2.LowRow And ViewNumber2.HighRow

In the code I show above, ViewNumber2 is the view that contains the HighRow and LowRow data. ViewNumber1 is the other view. You'll need to change them both to the actual view names.

-George
Microsoft SQL Server MVP
My Blogs
SQLCop
twitter
"The great things about standards is that there are so many to choose from." - Fortune Cookie Wisdom
 
George, that was the first thing that I tried (sorry, I should have said that), but it does not give me the data that I need. To (hopefully) explain more fully a participant has a visit every (roughly) three months. At that visit their PSA value is recorded along with the date. Now, what I need to do is grab each date, go back 24 months and make sure there are at least 5 PSA values in that time frame (this is what view number 2 does). So, view number 1 has all of the data and view number 2 tells me what the breakdown for each set of data should be. So, this is where I stand right now.

Now, I have to use those upper and lower values (created rowids) to grab the actual PSA values for each range for each participant. I then need to do some calculations with those PSA values. I could do this in classic asp using ADO recordsets, but the way it is going to be used, creating a final view would be the most helpful route. So, what I want to get when I loop through each row in view number 2 (pulling data from view number 1) is

Code:
RowID	study_participant_id	proc_labs_psa_date	proc_labs_psa_value	Phase	inidate
10	08800021	2010-09-24 00:00:00.000	1.50	FU	2013-01-22 10:04:51.117
11	08800021	2010-12-29 00:00:00.000	1.40	FU	2013-01-22 10:04:51.117
12	08800021	2011-04-14 00:00:00.000	1.80	FU	2013-01-22 10:04:51.117
13	08800021	2011-06-24 00:00:00.000	1.60	FU	2013-01-22 10:04:51.117
14	08800021	2011-09-28 00:00:00.000	1.30	FU	2013-01-22 10:04:51.117
15	08800021	2011-12-16 00:00:00.000	1.90	FU	2013-01-22 10:04:51.117
16	08800021	2012-04-13 00:00:00.000	1.90	FU	2013-01-22 10:04:51.117
17	08800021	2012-08-08 00:00:00.000	1.90	FU	2013-01-22 10:04:51.117

I need a discreet set for 10-17 AND 9-16 AND 8-15 etc. Hey, do you think I could accomplish this by using a cte and partitioning the data by the rowid in view number 2?
 
This

Code:
declare @mrow int
declare @newid int
declare @spid int
declare @hr int
declare @lr int
declare @counter int
set @counter=1

SELECT @mrow=MAX(newrowid)
  FROM [dbEDRN195].[dbo].[PSALimits]
  
  
WHILE @counter<@mrow
begin
SELECT @newid=MIN(newrowid)
	   ,@spid=[Study_Participant_ID]
       ,@hr=[highrow]
       ,@lr=[lowrow]
  FROM [dbEDRN195].[dbo].[PSALimits]
  where newrowid=@counter
  group by Study_Participant_ID, highrow, lowrow


	select * from dbEDRN195.dbo.PSADates_Values
	where study_participant_id=@spid
	and RowID between @lr and @hr
	--select @newid=MIN(newrowid) from dbEDRN195.dbo.psalimits where newrowid>@newid
	
	set @counter = @counter+1
end

gives me the groupings that I am looking for, but it seems to be very slow.
 
unless I'm mistaken the sql you posted translates to the following

Code:
select * 
from dbEDRN195.dbo.PSADates_Values
inner join
(
select newrowid
      ,Study_Participant_ID as spid
      ,highrow as hr
      ,lowrow as lr
  FROM dbEDRN195.dbo.PSALimits
  where newrowid <= (select MAX(newrowid)
                       FROM dbEDRN195.dbo.PSALimits
                    )
  group by newrowid
          ,Study_Participant_ID
          ,highrow
          ,lowrow
) newid
on study_participant_id = spid
and RowId between lr and hr

Regards

Frederico Fonseca
SysSoft Integrated Ltd

FAQ219-2884
FAQ181-2886
 
Yes, that does give me the same results and much faster. Now, how would I step thru those as in an array without using a cursor inside T-SQL? This gives me (with some slight modifications) data in groupings (by participant id, and a ranked rowid). I then need to loop thru data from those groupings (psa date and value). I have done it in classic asp, but really would like to accomplish the task in a view for ease of use.
 
That was the issue, how to step thru a specified subset of data within T-SQL. In classic asp I took two comma delimited fields of values and placed them into arrays and the I stepped thru those arrays for my calculations. I could not see how to do this in T-SQL without using a loop and my data is ~5k rows with two fields that have 5-8 comma separated values that I placed into arrays and then loop thru, so I did not want to use cursors. IUn my web app I jsut did this

Code:
Dim strSQL, rsSQL, strSQL2, rsSQL2, pid, lr, hr, phase, psadate, psavalue, numvals, arrpsavals, arrpsadates
	dim tempCnt, fixedStartDate, psaLogValue, diffDate, slope, vNumerator, vDenominator, psaDoubleTime

	fixedStartDate = CDate("January 1, 1960")

	dim sumXY, sumX, sumY, sumXSq
	sumXY = 0
	sumX= 0
	sumY = 0
	sumXSq = 0

  strsql = "SELECT study_participant_id, lowrow, highrow FROM db.dbo.PSADTLimits where study_participant_id=08800021 order by study_participant_id, newrowid"
  Set rsSQL = RunWithRS(strSQL)

  if not rsSQL.BOF or not rsSQL.EOF then 
   while not rsSQL.EOF
   pid=rsSQL("study_participant_id")
   lr=rsSQL("lowrow")
   hr=rsSQL("highrow")
   numvals=(cint(hr)-cint(lr))+1
    strSQL2 = "SELECT distinct pdv.study_participant_id, phase, cast(proc_labs_psa_date as DATE) as psadate, proc_labs_psa_value , pl.valueset, pd.dateset " & _
                "FROM db.dbo.PSADates_Values as pdv join (select distinct study_participant_id, substring ( stuff( " & _
                              "( " & _
                                "select ' , ' + cast(proc_labs_psa_value as varchar(max)) " & _
                                "from db.dbo.PSADates_Values " & _
                                "where study_participant_id = "&pid&" and RowID between "&lr&" and "&hr&" " & _
                                "order by proc_labs_psa_date " & _
                                "for xml path ('') ), " & _
                                "1 , " & _
                                "2 , " & _
                                "'') " & _
                                ", 2 , 1000 ) as valueset " & _
         "from db.dbo.PSADates_Values as results) as pl on pdv.study_participant_id=pl.study_participant_id " & _
        "join (select distinct study_participant_id, substring ( stuff( " & _
                                      "( " & _
                                        "select ' , ' + cast(cast(proc_labs_psa_date as date) as varchar(max)) " & _
                                        "from db.dbo.PSADates_Values " & _
                                "where study_participant_id = "&pid&" and RowID between "&lr&" and "&hr&" " & _
                                "order by proc_labs_psa_date " & _
                                "for xml path ('') ), " & _
                                "1 , " & _
                                "2 , " & _
                                "'') " & _
                                ", 2 , 1000 ) as dateset " & _
                 "from db.dbo.PSADates_Values as results) as pd on pdv.study_participant_id=pd.study_participant_id " & _
         "WHERE pdv.study_participant_id = " &pid& "and rowid= "&hr
    Set rsSQL2 = RunWithRS(strSQL2)
   phase=rsSQL2("phase")
   psadate=rsSQL2("psadate")
   psavalue=rsSQL2("proc_labs_psa_value")
   arrpsavals=Split(rsSQL2("valueset"),",")
   arrpsadates=Split(rsSQL2("dateset"),",")

      if not rsSQL2.BOF or not rsSQL2.EOF then 
       while not rsSQL2.EOF


		For tempCnt = 0 To UBound(arrpsavals)

		  diffDate = DateDiff("d", fixedStartDate, arrpsadates(tempCnt))   '                          : X
		  psaLogValue = Log(arrpsavals(tempCnt))                         'natural log of PSA value  : Y

		  sumXY = sumXY + (diffDate * psaLogValue)
		  sumX = sumX + diffDate
		  sumY = sumY + psaLogValue
		  sumXSq = sumXSq + (diffDate * diffDate)

		Next

		vNumerator = (sumXY) - ((sumX * sumY) / numvals)
		vDenominator = (sumXSq) - ((sumX * sumX) / numvals)

		slope = vNumerator / vDenominator

        psaDoubleTime = (Log(2) / slope)/365.25

But that looping and the array was what I could not see clear how to do in T-SQL.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top