2011-09-03 123 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的回答,試試這個查詢。它應該以您正在查找的形式返回結果集。

​​