2011-09-03 35 views
5

Tôi có ba bảng: enter image description here
Ví dụ ở đây là số liệu về cơ sở dữ liệu:

enter image description here
Có thể viết truy vấn mà cung cấp một mạng lưới như dưới đây cấu trúc?

enter image description here
Với viết truy vấn sử dụng đơn giản tham gia kết quả là như ở đây:

Tham cột SQL query

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

Tôi không hiểu những gì bạn đang yêu cầu. Bạn có thể rephrase nó? –

+0

Tắt chủ đề: Những gì bạn đang yêu cầu là có thể. Thứ nhất, điều này đang được tiêu thụ bởi một ứng dụng .NET? Tôi hỏi bởi vì nó sẽ sạch hơn nhiều để thực hiện chuyển đổi trong LINQ –

+0

@Neil Fenwick Đúng vậy. Xin vui lòng giải thích làm thế nào để tôi làm điều này bằng cách sử dụng LINQ? – Shahin

Trả lời

2

Cảm ơn bạn đã xác nhận điều này sẽ được tiêu thụ bởi .NET.

Lý do tôi hỏi là tôi không nghĩ rằng cơ sở dữ liệu là nơi tốt nhất để chuyển về số chuyển đổi dữ liệu. Không nói rằng bạn không bao giờ nên, chỉ là tốt nhất của nó để sử dụng cơ sở dữ liệu cho những gì tốt của nó tại: lưu trữ và lấy dữ liệu, và làm biến đổi trong mã tiêu thụ. Một nguyên tắc chung của nó là thử và làm theo nơi bạn có thể - nó để lại dữ liệu của bạn ở định dạng "thô" hơn và do đó nhiều khả năng có thể tái sử dụng và tiêu thụ được bởi các quy trình khác sau này.

Về cơ bản, tôi đã giải thích vấn đề là bạn muốn:

  1. nhóm của Liên và ContactType,
  2. và sau đó transpose & nối nhiều hàng số điện thoại.

Tôi không chắc chắn những gì mã NET của bạn mà các cuộc gọi cơ sở dữ liệu có vẻ như, nhưng bạn có thể làm như sau với một DataTable ví dụ (giả sử bạn có một cái gì đó giống như một loại 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(); 

Tôi không có IDE để kiểm tra, vì vậy hãy coi đó là mã thô. Bạn có được nguyên tắc từ nó mặc dù.

+0

+1 đây là nơi thích hợp để làm điều đó. Tôi sẽ +2 nếu tôi có thể cung cấp mã C#. –

+0

Cảm ơn Aaron :) –

7

Điều bạn đang tìm kiếm là tập hợp chuỗi. T-SQL không thực sự làm điều đó (các dbs khác có string_agg chẳng hạn). NHƯNG bạn có thể mô phỏng nó.

Hãy thử tìm ví dụ: http://consultingblogs.emc.com/jamiethomson/archive/2009/07/16/string-aggregation-in-t-sql-amp-pl-sql.aspx

hoặc, đối với các Các nhà sưu:

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

nếu bạn tìm kiếm SQL Server trong liên kết cuối cùng, có ba cách khác nhau để làm điều đó.

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

Hãy thử mã này

1

Bạn có thể sử dụng CTE để thu thập dữ liệu trong khi xoay các số điện thoại thành danh sách được phân tách bằng dấu phẩy. Nó có thể không hiệu quả, nhưng nó là một thủ thuật tiện dụng.

Sau đây chạy trên AdventureWorks2008R2, mặc dù bạn sẽ cần thêm một số dữ liệu vào bảng Person.PersonPhone để tạo nhiều số điện thoại cho một kiểu người/số.

; 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

Dựa trên phân loại trên câu trả lời của Aaron, hãy thử truy vấn này. Nó sẽ trả về một tập kết quả trong biểu mẫu bạn đang tìm kiếm.

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 
Các vấn đề liên quan