June 24, 2009 at 9:17 am
I am trying to return the first value of a field from a result set that is grouped.
To see a snap shot of the data I am pulling from I ran:
select top 5 CallerNum,sessionId, targetnum
from cdrmain
where (CONVERT(datetime, CAST(LocalDay AS varchar(10)), 101) >= DATEADD(day, - 7, GETDATE()))
and callernum = '233'
order by sessionId
Results:
Callernum sessionId targetnum
233124488162313014744242
233124488162616147645070
233124488169517346773000
233124488170115706893353
233124488170415706893353
I need to be able to do a group by on Callernum(233) but get the first result from the targetnum field (13014744242).
When running the query with the group by on callernum, I use the min aggregate function and it returns the smallest value even though it isn't the first value.
select CallerNum,min(sessionId) sessionId, min(targetnum) targetnum
from cdrmain
where (CONVERT(datetime, CAST(LocalDay AS varchar(10)), 101) >= DATEADD(day, - 7, GETDATE()))
and callernum = '233'
group by callernum
Results:
CallerNum sessionId targetnum
233124488162312404324556
Any ideas?
June 24, 2009 at 1:57 pm
Try this out.
-- Notice how I built a table and populated it with your test data?
-- this makes it MUCH easier for people to help you out
-- all they have to do is cut and paste, and they can get right to it.
-- just like you're going to do with this code!
-- also, I had to make assumptions about your data types. If you had
-- supplied them, then we wouldn't have to do that.
-- See the link in my signature for how to do this.
declare @tmp table (Callernum int, sessionId bigint, targetnum bigint)
insert into @tmp
SELECT 233, 1244881623, 13014744242 UNION ALL
SELECT 233, 1244881626, 16147645070 UNION ALL
SELECT 233, 1244881695, 17346773000 UNION ALL
SELECT 233, 1244881701, 15706893353 UNION ALL
SELECT 233, 1244881704, 15706893353
-- show what's in this table
select * from @tmp
-- use a common-table expression with the row_number() function.
;with CTE AS
( -- get row numbers for the data, resetting at 1 at each change in Callernum
select Callernum,
sessionId,
targetnum,
ROW_NUMBER() OVER (PARTITION BY Callernum order by CallerNum) AS RowNbr
from @tmp
)
-- get just the rows with RowNbr = 1
select Callernum,
sessionId,
targetnum
from CTE
where RowNbr = 1
Wayne
Microsoft Certified Master: SQL Server 2008
Author - SQL Server T-SQL Recipes
June 24, 2009 at 2:46 pm
If you need to get the first value for a given Callernum (like in your example for '233'), you simply could use top 1 clause (based on Wayne's sample data - Thanx for providing! ):
SELECT TOP 1 CallerNum, sessionId, targetnum
FROM @tmp
WHERE
callernum = '233'
ORDER BY sessionId, targetnum
@Wayne: When the request is to get the values for more than one Callernum, I'd go with your solution, but I would change
ROW_NUMBER() OVER (PARTITION BY Callernum order by CallerNum) AS RowNbr
to
ROW_NUMBER() OVER (PARTITION BY Callernum order by CallerNum, sessionId, targetnum) AS RowNbr
to ensure to get the first sessionid and the first targetnum at position 1.
If not, you might end up with a different order if the data weren't inserted in the proper order.
Example:
Check the result of your code with the following insert order:
insert into @tmp
SELECT 233, 1244881695, 17346773000 UNION ALL
SELECT 233, 1244881623, 13014744242 UNION ALL
SELECT 233, 1244881626, 16147645070 UNION ALL
SELECT 233, 1244881701, 15706893353 UNION ALL
SELECT 233, 1244881704, 15706893353
June 24, 2009 at 5:53 pm
lmu92 (6/24/2009)
@Wayne
: When the request is to get the values for more than one Callernum, I'd go with your solution, but I would changeROW_NUMBER() OVER (PARTITION BY Callernum order by CallerNum) AS RowNbr
to
ROW_NUMBER() OVER (PARTITION BY Callernum order by CallerNum, sessionId, targetnum) AS RowNbr
to ensure to get the first sessionid and the first targetnum at position 1.
If not, you might end up with a different order if the data weren't inserted in the proper order.
Lutz:
good call. However, I did it this way on purpose. In the original post, the OP stated:
When running the query with the group by on callernum, I use the min aggregate function and it returns the smallest value even though it isn't the first value.
Based on this, I figured that he didn't want the smallest, but instead what was actually first, regardless of the sorting. Ordering by the other fields would have done this.
Wayne
Microsoft Certified Master: SQL Server 2008
Author - SQL Server T-SQL Recipes
June 24, 2009 at 6:38 pm
Thank you both for your responses. While I was waiting I cobbled together my own solution which was to concatenate the sessionid and callernum grab the min from there and then separate the two in the application.
Viewing 5 posts - 1 through 5 (of 5 total)
You must be logged in to reply to this topic. Login to reply