I'm trying to figure out how best to query a schema consisting of one central table, plus a lot of attribute tables (sorry, not sure of the best terminology here) that record one-to-many relationships. In the business layer, each of these tables corresponds to a collection, which may contain zero or more elements.
Currently, the code I'm looking for retrieves data, retrieving a list of values ββfrom the main table, then iterating over it and querying each of the "auxiliary" tables to populate these collections.
I would like to try and bring it to one request, if possible. I tried to use multiple LEFT JOIN s. But this effectively connects to the cross product of the values ββin the accessory tables, which leads to a row explosion - especially when you add a few more compounds. There are five such relationships in the table under consideration, so the number of rows returned for each record is potentially huge and almost entirely composed of redundant data.
Here's a small synthetic example of some tables, data, the query structure I use, and the results:
Database structure and data:
create table Containers ( Id int not null primary key, Name nvarchar(8) not null); create table Containers_Animals ( Container int not null references Containers(Id), Animal nvarchar(8) not null, primary key (Container, Animal) ); create table Containers_Foods ( Container int not null references Containers(Id), Food nvarchar(8) not null, primary key (Container, Food) ); insert into Containers (Id, Name) values (0, 'box'), (1, 'sack'), (2, 'bucket'); insert into Containers_Animals (Container, Animal) values (1, 'monkey'), (2, 'dog'), (2, 'whale'), (2, 'lemur'); insert into Containers_Foods (Container, Food) values (1, 'lime'), (2, 'bread'), (2, 'chips'), (2, 'apple'), (2, 'grape');
In combination with a business object like this:
class Container { public string Name; public string[] Animals;
And here is how I build a query against it:
select c.Name container, a.Animal animal, f.Food food from Containers c left join Containers_Animals a on a.Container = c.Id left join Containers_Foods f on f.Container = c.Id;
What gives these results:
container animal food --------- -------- -------- box NULL NULL sack monkey lime bucket dog apple bucket dog bread bucket dog chips bucket dog grape bucket lemur apple bucket lemur bread bucket lemur chips bucket lemur grape bucket whale apple bucket whale bread bucket whale chips bucket whale grape
Instead, I would like to see several rows equal to the maximum number of values ββassociated with the root table, in any of the relationships, with an empty space filled with NULL. This will save the number of rows returned in a way, way, way down, while at the same time easily converting to objects. Something like that:
container animal food --------- -------- -------- box NULL NULL sack monkey lime bucket dog apple bucket lemur bread bucket whale chips bucket NULL grape
Can this be done?