Соединить столбцы SQL-запрос - PullRequest
5 голосов
/ 03 сентября 2011

У меня есть три таблицы: enter image description here
Например вот данные в базе данных:

enter image description here
Можно ли написать запрос, который обеспечивает сетку, как показано ниже структуры?

enter image description here
При написании запроса с использованием простого соединения результат выглядит так:

SELECT     dbo.Contact.ContactID, dbo.Contact.ContactName, dbo.PhoneNumber.PhoneNO, dbo.PhoneType.TypeTitle
FROM         dbo.Contact INNER JOIN
                      dbo.PhoneNumber ON dbo.Contact.ContactID = dbo.PhoneNumber.ContactID AND dbo.Contact.ContactID = dbo.PhoneNumber.ContactID INNER JOIN
                      dbo.PhoneType ON dbo.PhoneNumber.PhoneType = dbo.PhoneType.PhoneTypeI

enter image description here

Ответы [ 6 ]

7 голосов
/ 03 сентября 2011

То, что вы ищете, - это агрегирование строк.T-SQL изначально не делает этого (например, в других БД есть string_agg).НО вы можете имитировать это.

Попробуйте поискать, например: http://consultingblogs.emc.com/jamiethomson/archive/2009/07/16/string-aggregation-in-t-sql-amp-pl-sql.aspx

или, для полных списков:

http://www.postgresonline.com/journal/archives/191-stringagg.html

, если вы ищетедля SQL Server в последней ссылке есть три различных способа сделать это.

2 голосов
/ 03 сентября 2011

Спасибо за подтверждение, что это будет использовано .NET.

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

По сути, я интерпретировалпроблема в том, что вы хотите:

  1. группировать по Contact и ContactType ,
  2. , а затем транспонировать и объединять несколько строк телефонных номеров .

Я не уверен, как выглядит ваш .NET-код, который вызывает базу данных, но вы могли бы сделать следующее, например, с DataTable (при условии, что у вас есть что-то вроде Contactвведите):

List<Contact> results = (
    from dataRow in myDataTable.AsEnumerable()
    let contactData = new {
                           ContactName = dataRow.Field<string>("ContactName"),
                           PhoneType = dataRow.Field<string>("PhoneType"),
                           PhoneNumber = dataRow.Field<string>("PhoneNO")
                      }
    group contactData by new { contactData.ContactName, contactData.PhoneType } into grp
    select new Contact {
           ContactName = grp.Key.ContactName,
           PhoneType = grp.Key.PhoneType,
           PhoneNumber = grp.Aggregate( (cumulativeText, contact) => String.Format("{0}, {1}", cumulativeText, contact.PhoneNumber) )
    }
).ToList();

У меня не было IDE для тестирования, поэтому примите это за грубый код.Вы получаете принцип из этого, хотя.

1 голос
/ 03 сентября 2011

Вы можете использовать CTE для сбора данных при повороте телефонных номеров в список через запятую.Это может быть неэффективно, но это удобный трюк.

Следующее работает на AdventureWorks2008R2, хотя вам нужно будет добавить некоторые дополнительные данные в таблицу Person.PersonPhone, чтобы создать несколько телефонных номеров для одного человека./ номер типа.

; with PersonsWithTelephoneNumbersCTE (
  BusinessEntityId, FirstName, MiddleName, LastName,
  PhoneNumberTypeId, PhoneNumber, PhoneNumbers, Elements )
as (
  -- Base case: Just the person identifications with all possible phone types.
  select BusinessEntityID, FirstName, MiddleName, LastName, PhoneNumberTypeId,
    cast( '' as NVarChar(25) ), cast( '' as VarChar(MAX) ), 0
    from Person.Person as PP cross join
      Person.PhoneNumberType as PNT
  union all
  -- Add a telephone number.
  select CTE.BusinessEntityId, CTE.FirstName, CTE.MiddleName, CTE.LastName,
    PNT.PhoneNumberTypeID, PN.PhoneNumber,
    cast( CTE.PhoneNumbers + ', ' + PN.PhoneNumber as VarChar(MAX) ), CTE.Elements + 1
    from PersonsWithTelephoneNumbersCTE as CTE inner join
      Person.Person as PP on PP.BusinessEntityID = CTE.BusinessEntityId inner join
      Person.PhoneNumberType as PNT on PNT.PhoneNumberTypeID = CTE.PhoneNumberTypeId inner join
      Person.PersonPhone as PN on PN.BusinessEntityID = CTE.BusinessEntityId and PN.PhoneNumberTypeID = PNT.PhoneNumberTypeID
    where PN.PhoneNumber > CTE.PhoneNumber
  )
-- Get the person and the longest list of phone numbers for each person/phone type.
select LastName, FirstName, MiddleName,
  (select Name from Person.PhoneNumberType where PhoneNumberTypeID = Edna.PhoneNumberTypeID ) as PhoneNumberType,
  substring( PhoneNumbers, 3, len( PhoneNumbers ) - 2 ) as PhoneNumbers from (
  select BusinessEntityID, FirstName, MiddleName, LastName, PhoneNumberTypeId, PhoneNumbers,
    rank() over ( partition by BusinessEntityId, PhoneNumberTypeId order by Elements desc ) as Ranking
    from PersonsWithTelephoneNumbersCTE
  ) as Edna
  where Ranking = 1 and PhoneNumbers <> ''
  order by LastName, FirstName, MiddleName, PhoneNumberType
1 голос
/ 03 сентября 2011
select stuff((select distinct ','+ numbers from testtable for xml path('')),1,1,'')

Попробуйте этот код

0 голосов
/ 05 сентября 2011

Исходя из ответа Аарона, попробуйте этот запрос.Он должен вернуть набор результатов в форме, которую вы ищете.

    SELECT DISTINCT
    c.ContactName
    ,pt.TypeTitle
    ,(SELECT pn2.PhoneNO + ', '
        FROM dbo.PhoneNumber AS pn2
        WHERE pn.PhoneType = pn2.PhoneType
            AND pn.ContactID = pn2.ContactID
        FOR XML PATH ('')
    ) AS Numbers
FROM dbo.Contact AS c
    INNER JOIN dbo.PhoneNumber AS pn
        ON c.ContactID = pn.ContactID
    INNER JOIN dbo.PhoneType AS pt
        ON pn.PhoneType = pt.PhoneTypeID
0 голосов
/ 03 сентября 2011

В Mysql есть функция GROUP_CONCAT, которая сделает это за вас. AFAIK MSSQL не имеет эквивалента, но, возможно, этот блог приведет вас ближе к вашей цели: http://explainextended.com/2010/06/21/group_concat-in-sql-server/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...