2011-09-03 99 views
5

我有三个表: enter image description here
例如这里是数据库中的数据:

enter image description here
是否有可能编写查询提供的网格状结构如下?使用简单连接的结果

enter image description here
随着书写的查询是喜欢这里:

加入列SQL查询

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

+0

我不明白你在问什么。你能重述吗? – 2011-09-03 08:09:32

+0

偏题:你问的是可能的。首先,这是由.NET应用程序消耗吗?我问,因为LINQ中的转置要干净得多 –

+0

@ Neil Fenwick 是的。请你解释一下如何使用LINQ来做这件事?的 – Shahin

回答

2

感谢确认这将是由.NET消耗。

,我问的原因是,我不认为该数据库是去转化数据的最佳场所。并不是说你永远不应该这样做,只是最好的方式是使用数据库来实现其优点:存储和检索数据,并在消费代码中进行转换。它的一个普遍原则是尽可能地尝试并遵循 - 它将数据保留在更“原始”的格式中,因此更容易被以后的其他进程重用和消费。

从本质上讲,我已经解释的问题是,你想:

  1. 组的联系和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来测试,所以把它当成粗糙的代码。尽管如此,你从中得到了原则。

+0

+1这是正确的地方。如果我能提供C#代码,我也会+2。 –

+0

谢谢Aaron :) –

1
select stuff((select distinct ','+ numbers from testtable for xml path('')),1,1,'') 

试试这个代码

1

您可以使用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 
0

根据Aaron的回答,试试这个查询。它应该以您正在查找的形式返回结果集。

​​