tags:

views:

60

answers:

3

I have a database table full of time points and experimental values at those time points. I need to retrieve the values for an experiment and create a thumbnail image showing an XY plot of its data. Because the actual data set for each experiment is potentially 100,000 data points and my image is only 100 pixels wide, I want to sample the data by taking every nth time point for my image and ignoring the rest.

My current query (which retrieves all the data without sampling) is something simple like this:

var points = from p in db.DataPoints
             where p.ExperimentId == myExperimentId
             orderby p.Time
             select new {
                            X = p.Time,
                            Y = p.Value
                        }

So, how can I best take every nth point from my result set in a LINQ to SQL query?

+1  A: 
.Skip(n).Take(1)

Will return one sample point. Call it repeatedly to get more points.

http://msdn.microsoft.com/en-us/library/bb386988.aspx

If performance becomes an issue, and you have a primary identity key of type int containing consecutive values, you can try returning all records that will evenly divide the primary key by your n.

.Where(x => x.PK % n == 0)
Robert Harvey
This doesn't do every Nth point, though...
Reed Copsey
@Reed: it does if you call it repeatedly.
Robert Harvey
Ouch - take one point at a time, for the entire sequence? That's harsh :)
Reed Copsey
@Robert: It's doable in a single query, though...
Reed Copsey
@Reed: It would depend on how big n is. See my edit for an alternate possible solution.
Robert Harvey
I think the modulus of the primary key is the best way to go. Thanks. I'll try that. There's no guarantee that they are an uninterrupted sequence, but I think it'll probably work for me.
Chris Farmer
@Chris: If you want every nth after sorting, see my answer... If you don't care about the ordering, then using the key is probably the best option.
Reed Copsey
A: 

You should you

.Skip(n).Take(100)

It skips how many every record you want it to skip and Takes 100 records.

HTH

Raja
That will skip n records and take the next 100 consecutive ones.
Robert Harvey
This doesn't do every Nth point, though...
Reed Copsey
+2  A: 

This will do every nth element:

int nth = 100;
var points = db.DataPoints
           .Where(p => p.ExperimentId == myExperimentId)
           .OrderBy(p => p.Time)
           .Where( (p, index) => index % nth == 0 )
           .Select( p => new { X = p.Time, Y = p.Value } );

It works by using the Queryable.Where overload which provides an index in the sequence, so you can filter based off the index.

Reed Copsey
+1 for the overloaded Where.
Robert Harvey
Thanks! This idea seems to work nicely.
Chris Farmer