2016-04-22 3 views
2

Можно ли даже такое сделать? Для приложения, которое я пытаюсь сделать, пользователь может вводить несколько (или нет) писем, телефонных номеров и адресов для одного контакта, однако на лицевой стороне страницы я хочу только показать номер телефона, адрес электронной почты и адрес для каждого контакта (если таковой имеется).Как выбрать только один ряд из всех столбцов, но первый

Вот мой SQL запрос для получения данных (. Обратите внимание, что он был немного изменен для удобства чтения на практике, я не запрашивая SQL для печенья.):

SELECT TC.FirstName + ' ' + TC.LastName AS FullName, TCE.EmailAddress, TCPN.PhoneNumber, TCA.[Address] + ", " + TCA.City + ', ' + TCA.[State] + ', ' + TCA.ZipCode AS FullAddress, TC.Notes 
FROM TContacts     AS TC 
INNER JOIN TContactEmails  AS TCE ON TCE.ContactID = TC.ContactID 
INNER JOIN TContactPhoneNumbers AS TCPN ON TCPN.ContactID = TC.ContactID 
INNER JOIN TContactAddresses AS TCA ON TCA.ContactID = TC.ContactID 
INNER JOIN TUserContacts  AS TUC ON TUC.ContactID = TC.ContactID 
INNER JOIN TUsers    AS TU ON TU.UserID = TUC.UserID 
WHERE TU.UserName = userCookie.Values["UserName"] 

Нужный результат будет что-то похожее на использование SELECT TOP 1 вместо SELECT, однако я не могу этого сделать специально, потому что тогда он будет отображать только первый контакт (FullName). Мне нужно увидеть каждое имя, но не каждый FullAddress, PhoneNumber или EmailAddress.

Следующая информация предназначена, если есть другое решение, не связанное с SQL-запросом.

Этот SQL-запрос используется на веб-странице с использованием кода ASP.NET и C# и вызывается через команды ADO.NET. После вызова запроса все используемые таблицы загружаются в объект DataAdapter и используются для динамического заполнения ListView. Вот код, который (SQLStatement опущен, так как он, по существу, перечисленных выше):

 SqlConnection conn = new SqlConnection(WebConfigurationManager.ConnectionStrings["CPDM_NightingaleAConnectionString"].ConnectionString); 
     SqlCommand comm = new SqlCommand(sqlStatement, conn); 

     comm.CommandType = CommandType.Text; 
     comm.Connection = conn; 

     conn.Open(); 

     SqlDataAdapter dataAdapter = new SqlDataAdapter(comm); 
     DataSet ds = new DataSet(); 
     dataAdapter.Fill(ds, "TUsers, TUserContacts, TContactAddresses, TContactPhoneNumbers, TContactPhoneNumbers, TContactEmails, TContacts"); 
     lvContacts.DataSource = ds.Tables[0]; 
     lvContacts.DataBind(); 

     conn.Close(); 

код ASP.NET для ListView динамически создает таблицу на основе значений, например, так:

<asp:ListView ID="lvContacts" runat="server"> 
     <ItemTemplate> 
      <tr> 
       <td><asp:LinkButton ID="LinkButton1" runat="server" Text='<%# Eval("FullName") %>' /></td> 
       <td><asp:LinkButton ID="LinkButton2" runat="server" Text='<%# Eval("EmailAddress") %>' /></td> 
       <td><asp:LinkButton ID="LinkButton3" runat="server" Text='<%# Eval("PhoneNumber") %>' /></td> 
       <td><asp:LinkButton ID="LinkButton4" runat="server" Text='<%# Eval("FullAddress") %>' /></td> 
       <td><asp:LinkButton ID="LinkButton5" runat="server" Text='<%# Eval("Notes") %>' /></td> 
      </tr>  
     </ItemTemplate> 
    </asp:ListView> 

Это отнюдь не самая элегантная реализация такой функции, как это, но в ее нынешнем виде я не эксперт ни в одном из инструментов, которые я использую. Любая помощь по этой теме была бы весьма признательна.

В качестве дополнения, если кто-либо знает, как добавить разрыв строки в середине инструкции SQL SELECT, которая будет отображаться при преобразовании в HTML, это было бы очень полезно для организации FullAddress. CHAR(10) + CHAR(13) действительно ничего не значил.

+0

Что касается разрыва строки, может быть лучше оставить адрес отдельно в вашем операторе SQL и сломать его в коде кнопки ссылки, используя '<% # Eval (« Address ») + Environment. NewLine + Eval («Город») + «,» + Eval («State») + «+ Eval (« ZipCode »)%>' –

ответ

4

Вы можете использовать подзапрос, который, как правило, хорошо для этих типов поисков:

SELECT TC.FirstName + ' ' + TC.LastName AS FullName, 
(SELECT TOP 1 EmailAddress FROM TContactEmails WHERE ContactID = TC.ContactID) AS EmailAddress, 
(SELECT TOP 1 PhoneNumber FROM TContactPhoneNumbers WHERE ContactID = TC.ContactID) AS PhoneNumber, 
(SELECT TOP 1 [Address] + ", " + City + ', ' + [State] + ', ' + ZipCode FROM TContactAddresses WHERE ContactID = TC.ContactID) AS FullAddress, 
TC.Notes 
FROM TContacts     AS TC 
INNER JOIN TUserContacts  AS TUC ON TUC.ContactID = TC.ContactID 
INNER JOIN TUsers    AS TU ON TU.UserID = TUC.UserID 
WHERE TU.UserName = userCookie.Values["UserName"] 

в качестве альтернативы, использовать «по умолчанию» логическое в таблице и позволяет пользователю вводить данные сохранить свой адрес по умолчанию, номер телефона и т. д.

+1

Это тоже ответ, но если у вас есть большое количество записей в TContac, внешнее применение выполняется намного лучше, чем подзапрос. – FLICKER

+0

Я не анализировал производительность, поэтому не уверен. Но, по крайней мере, мы дали ему несколько вариантов. :) –

+0

@BoydP Спасибо! Это работает безупречно. Моя программа довольно маленькая, поэтому масштаб не будет проблемой, но Flicker, спасибо за ваш ответ. Я даже не знал, что до сих пор существовали перекрестные соединения, и я видел, что ваше редактирование на внешнем языке применяется, поэтому я посмотрю, смогу ли я заставить это работать позже, но на данный момент это соответствует моим потребностям. Спасибо вам обоим! – user3530169

1

Вы можете выбрать первый телефон для каждого контакта, используя Cross Join (не внутреннее соединение), как показано ниже общего примера

select TC.*, pho.Phone, adr.[Address] 
from TContact AS TC 
    outer apply (select top 1 phone 
       from TContactPhoneNumbers 
       where ContactID = TC.ContactID) AS pho 
    outer apply (select top 1 [address] 
       from TContactAddresses 
       where ContactID = TC.ContactID) AS adr 
    outer apply (select top 1 [UserName] 
       from TUserContacts 
       where ContactID = TC.ContactID) AS uc 
    outer apply (select top 1 [UserName] 
       from TUsers 
       where UserId = uc.UserID) AS u 
where u.UserName = what ever ..... 

и добавить другие таблицы, как вы видите ...

+0

Это похоже на то, что я ищу, но как предложение where Работа? Я пытаюсь использовать 'WHERE TContactPhoneNumbers.ContactID = TContacts.ContactID', но я продолжаю получать сообщение об ошибке« TCActacts.ContactID с несколькими частями ». – user3530169

+0

Вы сглаживаете стол? Если вы сделали так, как Фликкер предложил «TContacts as tc», тогда вы должны использовать tc.ContactID, а не TContacts.ContactID. –

+0

@BoydP Я попробовал это сначала, оба TC.ContactID (с AS TC) и TContacts.ContactID (без AS TC) приводят к той же ошибке. – user3530169