2012-07-06 13 views
8

Vớihiệu quả Bao gồm cột không trong Nhóm By của SQL Query

Bảng A

Id INTEGER 
Name VARCHAR(50) 

Bảng B

Id INTEGER 
FkId INTEGER ; Foreign key to Table A 

tôi muốn đếm occurrances của mỗi giá trị FkId :

SELECT FkId, COUNT(FkId) 
FROM B 
GROUP BY FkId 

Bây giờ tôi chỉ muốn cũng xuất ra Tên từ Table A.

này sẽ không làm việc:

SELECT FkId, COUNT(FkId), a.Name 
FROM B b 
INNER JOIN A a ON a.Id=b.FkId 
GROUP BY FkId 

a.Name không được chứa trong mệnh đề GROUP BY (sản xuất is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause lỗi).

Vấn đề là để di chuyển từ đầu ra như thế này

FkId Count 
1  42 
2  25 

để đầu ra như thế này

FkId Count Name 
1  42  Ronald 
2  22  John 

Có khá một vài trận đấu trên SO cho rằng thông báo lỗi, nhưng một số ví dụ https://stackoverflow.com/a/6456944/141172 có các nhận xét như "sẽ tạo 3 lần quét trên bàn, thay vì 1, do đó sẽ không mở rộng".

Làm thế nào tôi có thể có hiệu quảbao gồm một trường từ gia nhập Table B (trong đó có một 1: mối quan hệ 1-FkId) trong kết quả truy vấn?

+0

Bạn có thể hiển thị một số dữ liệu mẫu và kết quả mong muốn không? Tôi đang có một thời gian khó hiểu nếu có thể có nhiều hơn một tên duy nhất cho mỗi FkId. –

+0

Sẽ chỉ có một tên duy nhất trên mỗi FkId. Vấn đề là chỉ hiển thị tên cùng với FkId để người dùng xem kết quả không thấy "Người 1 xuất hiện 42 lần" mà đúng hơn là "Người 1, có tên là Ronald, đã xuất hiện 42 lần". –

+1

Vậy tại sao không chỉ thêm Tên vào nhóm theo? –

Trả lời

12

Bạn có thể thử một cái gì đó như thế này:

;WITH GroupedData AS 
    (
     SELECT FkId, COUNT(FkId) As FkCount 
     FROM B 
     GROUP BY FkId 
    ) 
    SELECT gd.*, a.Name 
    FROM GroupedData gd 
    INNER JOIN dbo.A ON gd.FkId = A.FkId 

Tạo một CTE (Common Table Expression) để xử lý các nhóm/đếm trên Table B của bạn, và sau đó tham gia mà kết quả (một hàng cho mỗi FkId) đến Table A và lấy một số cột khác từ Table A vào tập kết quả cuối cùng của bạn.

+0

Đó là khá nhiều giống như các giải pháp tôi liên kết với, trong đó có nhận xét 'Và sẽ tạo ra 3 quét trên bàn, chứ không phải là 1, do đó, sẽ không scale'. Liệu giải pháp này có thực sự thực hiện 3 lần quét bảng khi người bình luận gợi ý không? –

+5

@EricJ .: Vâng - sao chép truy vấn, chạy nó trong SQL Server Mgmt Studio của bạn và có "thực thi kế hoạch thực hiện" bật, và bạn sẽ thấy rằng ** NO ** nó sẽ ** KHÔNG ** làm ba bảng quét .....nhận xét trong câu trả lời mà bạn đã liên kết là chính xác vì truy vấn có ** hai truy vấn con ** (SELECT ....) phụ thêm ** ** sẽ thêm một bảng quét mỗi (** NOT ** the CTE được sử dụng để nhóm!) –

+1

+1 để sử dụng kế hoạch thực thi thực tế để chẩn đoán hiệu suất. :-) –

3

Bạn đã thử thêm trường vào nhóm chưa?

SELECT FkId, COUNT(FkId), a.Name 
FROM B b 
INNER JOIN A a ON a.Id=b.FkId 
GROUP BY FkId,a.Name 
0
select t3.Name, t3.FkId, t3.countedFkId from (a t1 
    join (select t2.FkId, count(FkId) as countedFkId from b t2 group by t2.FkId) 
    on t1.Id = t2.FkId) t3; 
+1

Hãy sử dụng '{}' not 'để đánh dấu các khối mã. Và đừng sợ trả về vận chuyển. Ngoài ra tôi không nghĩ rằng truy vấn này phân tích cú pháp (bảng dẫn xuất cần một bí danh). –

+0

Ồ, cảm ơn lời khuyên. Vẫn còn mới với cú pháp ở đây :) Và tôi đoán bạn đang đúng về việc cần một bí danh cho bảng dẫn xuất. – germi