2014-01-22 4 views
0

позволяет сказать, что здесь моя структура БДSQL - несколько запросов или один присоединиться к

TableA 
{ 
    [ID] INT IDENTITY (1, 1) primary key, 
    [Title] varchar (50) NOT NULL, 
    [Details] varchar(50) NOT NULL 
} 

TableB: 
{ 
    [ID] INT foreign key references [TableA] ([ID]) 
    [AvailableTime] DATETIME NOT NULL 
} 

TableC: 
{ 
[ID] INT foreign key references [TableA] ([ID]) 
[AvailableLocation] varchar(50) NOT NULL 
} 

мне нужны все столбцы из таблицы А, а также список AvailableTimes из таблицы B для конкретного ID

результат должен выглядеть следующим образом: новый объект (id, title, details, List availableTime);

может быть несколько доступных для одного ID. Было бы лучше, если бы я сделал два отдельных запроса, чтобы получить эту информацию или сделать соединение, а затем перебирать два раза. I.E.

select * from TableA where ID = 1; 
select * from TableB where ID = 1; 
select * from TableC where ID = 1; 

...

ИЛИ

select * from TableA inner join TableB on TableA.ID = TableB.ID inner join TableC on TableA.ID = TableC.ID where ID = 1 
List<DateTime> availableTime = new List<DateTime>(); 
foreach(DataRow row in resultTable.Rows) 
{ 
    if (!availableTime.Contains((DateTime) row["AvailableTime"])) 
     availableTime.Add((DateTime) row["AvailableTime"]); 
} 

foreach(DataRow row in resultTable.Rows) 
{ 
    if (!availableLocation.Contains((string) row["AvailableTime"])) 
     availableLocation.Add((string) row["AvailableLocation"]); 
} 
return new object (id, resultTable.Rows[1], resultTable.Rows[2], availableTime, availableLocation); 

Я делаю это на сервере (ASP.NET) и сервер отвечает за обе выполнения запроса и обработки данных перед ним отправляется пользователю.

Заранее спасибо.

+2

Было бы проще предоставить правильный ответ и помочь, если вы могли бы поделиться своей схемой таблиц – Tommassiov

+0

, выполнить оба запроса и посмотреть, какая из них лучше. Иногда запуск двух простых запросов лучше одного сложного запроса. Все зависит от этого, и с указанной информацией трудно сказать. Вы должны проверить это. –

+0

Вам нужно будет обработать на клиенте в любом случае, чтобы получить «дерево» из SQL. SQL возвращает * табличные * данные. В C# такое преобразование (при сохранении одного запроса) тривиально с LINQ. – user2864740

ответ

0

Вам нужно будет обработать на клиенте в любом случае, чтобы получить «дерево» из SQL. SQL возвращает табличные данные, которые де-нормированы.


Производительность мудрый и скорость мудрый, было бы лучше, если бы я сделать два отдельных запросов, чтобы получить эти данные или сделать объединение, а затем цикл по списку дважды?

Обычно, делая соединение в SQL быстрее и проще. Ручное циклическое SQL-выбор в коде является одним из способов: эффективно делает RA бесполезным, так как любое объединение хэшей/слияния превращается в «вложенные петли».

Поскольку C# поддерживает такое преобразование тривиально с помощью LINQ, это мое «первое предпочтение» - хорошо, сначала после использования поставщика Bonafide LINQ-to-Database - для решения этой проблемы.

Возьмите запрос (где я переименованный «ID» для здравого смысла):

SELECT i.item_id, i.title, i.details, t.available_time 
FROM items i 
JOIN times t ON t.item_id = i.item_id 

соединяемых форма будет возвращать результат-набор (item_id, title, details, available_time).

Теперь, чтобы прочитать результат запроса в виде набора «readItems», чтобы тип соответствовал IEnumerable<{of the same fields as above}>, а затем перестроил древовидную структуру из данных.

var items = readItems 
    // The group by "re-normalize" on the key and the selector 
    // is still key on RS - as the title/details are FDs on item_id 
    .GroupBy(i => new { i.item_id, i.title, i.details }) 
    .Select(g => new ItemWithTimes { 
     ItemId = g.Key.item_id, 
     Title = g.Key.title, 
     Details = g.Key.details, 
     // capture collected data 
     AvailableTimes = g, 
    }); 

Конечно, если вы используете LINQ-to-SQL поставщика/EF (вместо воображаемых LINQ-to-Objects выше), то вы можете пропустить вручную происходит через плоские "ReadItems" result- задавать.


Есть некоторые исключения, как правило, с гипер-де-нормированный результат-множеств, где множество запросов может быть более подходящим - это, как правило, влияет на действительно глубокие деревьев или когда «большие» колонки дублируются.

Кроме того, некоторые базы данных, такие как SQL Server, поддерживают XML, которые могут обрабатывать гипердеформированные результирующие элементы (aka trees) без необходимости проходить через плоский табличный результирующий набор.

В любом случае, вы будете знать, что вам нужно это делать, когда придет время - и сохранение чистого DAL (вместо утечки доступа по всему месту) сделает изменяющиеся реализации относительно тривиальными.

+0

Могу ли я сделать то же самое, если у меня есть 3-я таблица, в которой я хочу получить список данных для – Steve

+0

@Steve Sure [вы бы просто группировали значения группы по соответствующему ключу для них], но затем вы вводите область «глубоких» деревьев и торговля большей эффективностью сервера (объединение RA) для снижения эффективности работы с клиентами (хотя групповая операция, вероятно, является хешированием). Есть точка перелома - и точка обслуживания. Я обычно просто позволяю LINQ2SQL делать всю тяжелую работу для меня. Честно говоря, во многих случаях это просто не имеет значения - и где это происходит, я фокусируюсь на «оптимизации». – user2864740

+0

Что делать, если сервер также обрабатывает данные, так как я работаю над проектом asp.net. – Steve

0

Если я правильно понял вопрос правильно, вам не нужно join вообще:

select PropertyA 
from tableA 
where id = XXX 
union all 
select PropertyC 
from tableB 
where id = XXX; 

Если вы хотите удалить дубликаты, изменить union all к union.

+0

право, союз, если он тоже. Но я все еще хочу знать, какой из них лучше работает. 2 запроса или 1 – Steve

+0

@Steve. , , Два запроса несут накладные расходы на подготовку запросов, их компиляцию и передачу их обратно в базу данных. Один запрос должен работать лучше. –

0

Простой присоединиться запрос будет что-то вроде этого

Select A.*, B.AvailableTime 
from TableA A 
inner join TableB B on A.ID=B.ID 

Но вы можете избежать дублирования с помощью конкатенации к одной запятой отдельную строку

select A.*, (SELECT ', ' + B.AvailableTime 
     FROM TableB B 
     WHERE A.ID=B.ID 
     FOR XML PATH('')) AS Timings 
from TableA A 

Но это зависит от ваших требований, которые один подходит вам лучше.

+0

Меня больше беспокоит производительность и скорость, а не сам запрос – Steve

+0

, а не отправка двух наборов результатов в приложение и соединение там, отправка одного набора результатов, очевидно, будет быстрее. если в результирующем наборе нет дубликатов, то это позволит сэкономить накладные расходы на отправку больших данных. попробуйте второй запрос. – Miller

Смежные вопросы