2010-01-20 40 views
5

Tôi mới để LINQ to SQL và tôi muốn biết làm thế nào để đạt được một cái gì đó như thế này trong LINQ:LINQ nhóm theo tháng câu hỏi

 Month Hires Terminations 
     Jan  5  7 
     Feb  8  8 
     Marc  8  5 

Tôi đã có này cho đến nay, và tôi nghĩ rằng có có vấn đề gì đó nhưng tôi không chắc chắn:

from term1 in HRSystemDB.Terminations 
group term1 by new { term1.TerminationDate.Month, term1.TerminationDate.Year } into grpTerm 
select new HiresVsTerminationsQuery 
{ 
    Date = Criteria.Period, 
    TerminationsCount = grpTerm.Count(term => term.TerminationDate.Month == Criteria.Period.Value.Month), 
    HiresCount = (from emp in HRSystemDB.Persons.OfType<Employee>() 
       group emp by new { emp.HireDate.Month, emp.HireDate.Year } into grpEmp 
       select grpEmp).Count(e => e.Key.Month == Criteria.Period.Value.Month) 
}); 

Xin cảm ơn trước.

+0

Hiển thị cho chúng tôi lược đồ cơ sở dữ liệu của bạn sẽ hữu ích. – Blindy

+0

'Tiêu chí.Period' và 'Tiêu chí.Period.Value.Month' là gì? –

+0

Điều gì khiến bạn cảm thấy không chắc chắn rằng điều đó đúng? Nó có biên dịch không? Bạn đã thử chạy nó chưa? Nó có đưa ra kết quả bạn mong đợi không? –

Trả lời

6

Tôi không chắc chắn giá trị Criteria.Period đến từ truy vấn mẫu của bạn ở đâu.

Tuy nhiên tôi nghĩ bạn đang cố gắng đọc cả việc thuê và chấm dứt cho tất cả các tháng có sẵn (và sau đó bạn có thể dễ dàng lọc nó). Truy vấn của bạn có thể sai nếu bảng đầu tiên (Chấm dứt) không bao gồm bất kỳ bản ghi nào cho một số tháng cụ thể (ví dụ: Tháng 5). Sau đó, mệnh đề select sẽ không được gọi với "Tháng Năm" làm tham số ở tất cả và ngay cả khi bạn có một số dữ liệu trong bảng thứ hai (đại diện cho Thuê), thì bạn sẽ không thể tìm thấy nó.

Điều này có thể được giải quyết một cách trang nhã bằng cách sử dụng Concat method (xem mẫu MSDN). Bạn có thể chọn tất cả termniations và tất cả các thuê (thành một cấu trúc dữ liệu của một số loại) và sau đó nhóm tất cả các dữ liệu theo tháng:

var terms = from t in HRSystemDB.Terminations 
      select new { Month = t.TerminationDate.Month, 
         Year = term1.TerminationDate.Year, 
         IsHire = false }; 
var hires = from emp in HRSystemDB.Persons.OfType<Employee>() 
      select new { Month = emp.HireDate.Month, 
         Year = emp.HireDate.Year 
         IsHire = true }; 

// Now we can merge the two inputs into one 
var summary = terms.Concat(hires); 

// And group the data using month or year 
var res = from s in summary 
      group s by new { s.Year, s.Month } into g 
      select new { Period = g.Key, 
         Hires = g.Count(info => info.IsHire), 
         Terminations = g.Count(info => !info.IsHire) } 

Khi nhìn vào mã bây giờ, tôi khá chắc chắn rằng có một số cách ngắn hơn để viết cái này. Mặt khác, mã này phải khá dễ đọc, đó là một lợi ích. Cũng lưu ý rằng việc phân chia mã thành một vài truy vấn phụ không quan trọng. Nhờ đánh giá chậm LINQ to SQL, điều này nên được thực hiện như một truy vấn đơn lẻ.

+0

Đây thực sự là một câu trả lời khá hay. Tôi không biết về phương pháp concat. Tôi sẽ thử nghiệm nó sau và đăng kết quả của tôi. Cảm ơn. – jasonco

+0

Bạn đã cứu mạng tôi. Làm việc tuyệt vời! Chỉ cần những gì tôi đang tìm kiếm. Cảm ơn! +1 – jasonco

3

Tôi không biết nếu nó ngắn hơn nhưng bạn cũng có thể thử phiên bản này để xem nó có hoạt động tốt hơn với máy chủ của bạn hay không. Tôi không biết chính xác hai câu trả lời này biến thành câu lệnh SQL như thế nào. Người ta có thể tốt hơn dựa trên chỉ mục của bạn và như vậy.

var terms = 
    from t in Terminations 
    group t by new {t.Month, t.Year} into g 
    select new {g.Key, Count = g.Count()}; 

var hires = 
    from p in Persons 
    group p by new {p.Month, p.Year} into g 
    select new {g.Key, Count = g.Count()}; 

var summary = 
    from t in terms 
    join h in hires on t.Key equals h.Key 
    select new {t.Key.Month, t.Key.Year, 
     Hires = h.Count, Terms = t.Count}; 
+0

Cảm ơn câu trả lời. Phiên bản này hoạt động miễn là có bất kỳ chấm dứt hoặc thuê nào trong cùng một tháng. Nếu không có thuê hoặc chấm dứt trong một trong số họ không có kết quả sẽ hiển thị cho tháng cụ thể đó, ngay cả khi có, nói 2 thuê nhưng 0 chấm dứt vào tháng Năm. Tôi phải chỉnh sửa nhỏ, nhóm (cho trường hợp cụ thể của tôi) phải là "nhóm t theo mới {t.TerminationDate.Month, t.TerminationDate.Year} thành g" và "nhóm p theo {p mới. ThuêDate.Month, p.HireDate.Year} vào g ". Ngoài ra tôi nghĩ đó là một câu trả lời hay. Cảm ơn! +1 :-) – jasonco

Các vấn đề liên quan