Я пытаюсь выяснить, как лучше всего выполнять запросы к схеме, состоящей из одной центральной таблицы, плюс несколько таблиц «атрибутов» (извините, не уверен в лучшей терминологии здесь), которые записывают один-ко-многимотношения.На бизнес-уровне каждая из этих таблиц соответствует коллекции, которая может содержать ноль или более элементов.
Прямо сейчас код, на который я смотрю, получает данные, получая список значений из основной таблицы,затем цикл по нему и запрос к каждой из «вспомогательных» таблиц для заполнения этих коллекций.
Я хотел бы попытаться свести его к одному запросу, если смогу.Я пытался использовать несколько LEFT JOIN
с.Но это эффективно объединяет перекрестное произведение значений в дополнительных таблицах, что приводит к взрыву строк - особенно когда вы добавляете еще несколько объединений.В рассматриваемой таблице пять таких отношений, поэтому число строк, возвращаемых для каждой записи, потенциально огромно и почти полностью состоит из избыточных данных.
Вот небольшой синтетический пример некоторых таблиц, данных и структуры запроса.Я использую, и результаты:
Структура базы данных и данные:
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');
В привязке к бизнес-объекту, как это:
class Container {
public string Name;
public string[] Animals; // may be empty
public string[] Foods; // may be empty
}
И вот способ, которым ястрою запрос против него:
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;
, который дает следующие результаты:
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
Вместо этого я хотел бы видеть количество строк, равное максимальному числузначения, связанные с корневой таблицей в любом из отношений, с пустым пространством, заполненным значениями NULL.Это позволило бы сохранить количество возвращаемых строк в обратном порядке, при этом их легко преобразовать в объекты.Примерно так:
container animal food
--------- -------- --------
box NULL NULL
sack monkey lime
bucket dog apple
bucket lemur bread
bucket whale chips
bucket NULL grape
Можно ли это сделать?