Question

I have a query like the following

select q1, q2, q3, q4, average from results

I need to calculate the average of q1 thru q5 in the average column for each row. I have the following

var query = from T in db.results
                        select new ResultsCustom
                        {
                            q1, q2, q3, q4
                            average = ((double)(T.q1 ?? 0.0)
                                + (double)(T.q2 ?? 0.0)
                                + (double)(T.q3 ?? 0.0)
                                + (double)(T.q4 ?? 0.0)
                                ) / 4};

The problem is that q1 thru q4 can be null which would throw the average off. If they are null I don't want to include them in the average calculation. I was thinking I could decrement the count if there is a null value. Is there a better way to do this?

Était-ce utile?

La solution

This won't be translatable to SQL but you could do:

var query = from T in db.results
            select new ResultsCustom
            {
                q1, q2, q3, q4
                average = (new double?[] { T.q1, T.q2, T.q3, T.q4 }).Average()
            };

since Average() will ignore null values.

To get the results and do the average in Linq-to-Objects do:

var query = (from T in db.results select new {q1, q2, q3, q4}).AsEnumerable()
            .Select(r => new ResultsCustom
                 {
                     r.q1, r.q2, r.q3, r.q4,
                     average = (new double?[] { r.q1, r.q2, r.q3, r.q4 }).Average()
                 }
             );

Autres conseils

You are not calculating an average there. Just use the standard formula sum / count.

...
let sum = q1.GetValueOrDefault() + q2.GetValueOrDefault() + ...
let count = (q1 != null ? 1 : 0) + ...
let avg = sum / count
...

You probably also need to define what should happen if count == 0.

double GetAverage(T)
{
    List<double> list = new List<double>();
    if (T.q1 != null) list.Add(T.q1);
    if (T.q2 != null) list.Add(T.q2);
    if (T.q3 != null) list.Add(T.q3);
    if (T.q4 != null) list.Add(T.q4);
    return list.Average();
}

You could generalise this as follows (not tested):

double GetAverage(List<double> doublesList)
{
    var list = doublesList.Where(x => x != null).ToList();
    return list.Average();
}

which returns the average of a list of doubles of any length, with nulls ignored, separating the process from the data acquisition.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top