Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does C# linq support "anti join" semantics?

I've googled a little while and didn't find a direct anti-join semantics example. How to do this in C# LINQ as an example?

like image 530
Troskyvs Avatar asked Sep 06 '25 20:09

Troskyvs


2 Answers

An anti-join as basically a set of data that is not conained in another set, can be represented in Linq with a an IEnumerable.Except like this:

double[] numbers1 = { 2.0, 2.0, 2.1, 2.2, 2.3, 2.3, 2.4, 2.5 };
double[] numbers2 = { 2.2 };

IEnumerable<double> onlyInFirstSet = numbers1.Except(numbers2);

foreach (double number in onlyInFirstSet)
    Console.WriteLine(number);

This of course requires the definition of an IEqualityComparer for custom classes.

An alternative syntax using where would be:

var antiJoin = numbers1.Where(number => !numbers2.Contains(number));

Read more on Enumerable.Except Method on Microsoft docs.

Edit:

As for "db driven linq" here is an example that will work for Entity Framework using Except:


var filteredProducts = db.Products.ToList()
    .Except(db.Orders.Where(o => o.OrderId = 123)
        .Select(o => o.Product).ToList())
    .ToList();

as for the where alternative:

var filterProducts = db.Orders.Where(o => o.OrderId = 123)
    .Select(o => o.Product).ToList();
var antiJoinProducts = db.Products.Where(p => !filterProducts.Contains(p));
like image 142
Raul Avatar answered Sep 08 '25 08:09

Raul


Assuming this relates to your previous question -

If you want to include in your query employees for which you couldn't find the department (essentially a left outer join) you can do this:

var result = from e in employees
                 join d in departments on e.DeptId equals d.DeptId into gj
                 from subdept in gj.DefaultIfEmpty()
                 select new { e.EmpName, subdept?.DeptName };

If you want to retrieve only the employees for which you couldn't match a department (that would be your anti join I guess) then you just add a subdept is null contition like so:

var result = from e in employees
                 join d in departments on e.DeptId equals d.DeptId into gj
                 from subdept in gj.DefaultIfEmpty()
                 where subdept is null
                 select new { e.EmpName, subdept?.DeptName };

For more info on left outer joins in C# Linq you can check this out.

like image 23
Marius Bughiu Avatar answered Sep 08 '25 09:09

Marius Bughiu