Search code examples
c#sqllinq-to-entities

Is it possible to count the number of condition a row have satisfied in linq to Entity Framework


I was wondering if there is a way to count the number of conditions a row has satisfied in order to sort the return value by the one which qualified most of the condition.

Let's say the table is something like this:

this

and let's say the condition is size=M or color=blue or size<40

What I expect as a result is something like this:

Id3 (3 conditions)
Id4 (2 conditions)
Id1 (1 condition)
Id2 (1 condition)

Solution

  • Here is one way to implement conditional aggregation using linq.

    Please note I've had to tweak your condition a bit because you wrote size=M or color=blue or size<40 - but size is either a string or a number, can't really be both - so I figured this is a typo and it was supposed to be size=M or color=blue or value<40.

    Also, since you didn't provide an MCVE, I did that for you (Please try to create an MCVE for your next questions)

    So let's start with a simple class for the data:

    class Data
    {
        public Data(string id, string size, int value, string color)
        {
            Id = id;
            Size = size;
            Color = color;
            Value = value;
        }
    
        public string Id {get;set;}
    
        public string Size {get;set;}
    
        public int Value {get;set;}
    
        public string Color {get;set;} 
    
        public override string ToString()
        {
            return string.Format("Id = {0}, Size = {1}, Value = {2}, Color = {3}", Id, Size, Value, Color);
        }
    }
    

    Now, let's create a list of that class and populate it with the sample data you've (kind of) provided:

    var sampleData = new List<Data>()
    {
        new Data("Id1", "L", 35, "red"),
        new Data("Id2", "L", 65, "blue"),
        new Data("Id3", "M", 34, "blue"),
        new Data("Id4", "S", 32, "blue"),
        new Data("Id5", "S", 55, "green")
    };
    

    Since I didn't want to write the conditions twice, I've decided to first select a new anonymous type that contain the Data class and another property I've called ConditionsMatched to hold the number of conditions this data actually matches. Then all I had to do is to filter the result of this select to return only those instances where the ConditionsMatched is larger than 0:

    var result = sampleData
        .Select(d => new 
                {
                    Data = d,
                    ConditionsMatched = 
                        (d.Size == "M" ? 1 : 0) +
                        (d.Color == "blue" ? 1 : 0) +
                        (d.Value < 40 ? 1 : 0)
                })
        .Where(a => a.ConditionsMatched > 0);
    

    The result is an IEnumerable<AnonymousType> that contains only the data that match at least one condition.

    You can see a live demo on rextester.