Set operations
Combine two queries with UNION, UNION ALL, INTERSECT, INTERSECT ALL, EXCEPT, or EXCEPT ALL.
Overview
Set operations combine the result sets of two compatible Query() builders. Both queries must return the same model type T.
Syntax
Call .Union(), .UnionAll(), .Intersect(), .IntersectAll(), .Except(), or .ExceptAll() on a query builder, passing a second TableQueryBuilder as the right operand:
var activeQuery = User.Query(x => x.IsActive == true);
var premiumQuery = User.Query(x => x.IsPremium == true);
await foreach (var user in activeQuery
.Union(premiumQuery)
.WithConnection(conn)
.ExecuteAsync())
{
Console.WriteLine(user.Username);
}Available operations
| Method | SQL |
|---|---|
.Union(other) |
UNION (deduplicated) |
.UnionAll(other) |
UNION ALL (includes duplicates) |
.Intersect(other) |
INTERSECT (deduplicated) |
.IntersectAll(other) |
INTERSECT ALL (includes duplicates) |
.Except(other) |
EXCEPT (deduplicated) |
.ExceptAll(other) |
EXCEPT ALL (includes duplicates) |
UNION ALL example
var recentQuery = Order.Query(x => x.CreatedAt > DateTime.UtcNow.AddDays(-7));
var pendingQuery = Order.Query(x => x.Status == "pending");
await foreach (var order in recentQuery
.UnionAll(pendingQuery)
.WithConnection(conn)
.ExecuteAsync())
{
Console.WriteLine($"{order.Id}: {order.Status}");
}Parameter handling
Both sub-queries share a single DbCommand. Parameters from the left and right queries are offset automatically, so there are no conflicts. You can safely reuse the same parameter values in both queries.
Compiled query interface
Every generated Query() builder implements ICompiledQuery internally, which is how its compiled SQL and parameters are merged into the combined command. Any builder can serve as either the left or right operand:
// either query can be on either side
await foreach (var row in leftQuery.Intersect(rightQuery).WithConnection(conn).ExecuteAsync())
{
// ...
}Limitations
- Both operands must return the same model type
T. - Set operations do not currently support chaining a
JOINbuilder on either operand. - The set-operation builder supports
Limit()andOffset()on the combined result.ORDER BYis not available. Sort in C# after collecting results if ordering is required.