2012-06-07 78 views
5

Tôi có một bảng có ba cột: A,B,C.Chọn hàng đầu tiên cho mỗi nhóm

Các giá trị là:

+---+-----+----+ 
| A | B | C | 
+---+-----+----+ 
| 1 | -10 | 5 | 
| 1 | 0 | 5 | 
| 1 | 10 | 5 | 
| 2 | 10 | 12 | 
| 2 | 0 | 12 | 
| 3 | -10 | 14 | 
| 4 | 0 | 8 | 
| 4 | 10 | 8 | 
| 5 | 0 | 6 | 
| 5 | 1 | 6 | 
| 5 | -5 | 6 | 
+---+-----+----+ 

Nếu lần đầu tiên tôi đặt các dữ liệu theo cột A, sau đó cột B, sau đó cột C (mặc dù tôi đã làm cho tất cả cột C giá trị như nhau cho mỗi giá trị cột A) sẽ như thế nào Tôi chọn "hàng đầu tiên" trên mỗi cột A?

Vì vậy, điều này sẽ dẫn đến:

+---+-----+----+ 
| A | B | C | 
+---+-----+----+ 
| 1 | -10 | 5 | 
| 2 | 0 | 12 | 
| 3 | -10 | 14 | 
| 4 | 0 | 8 | 
| 5 | -5 | 6 | 
+---+-----+----+ 
+0

người cuối cùng phải là {5, -5,6} – Kshitij

+0

Đã sửa lỗi ........... – mezamorphic

+0

Ngoài ra còn có câu trả lời chi tiết tại dba.stackexchange.com: [Đang truy xuất n hàng mỗi nhóm] (http://dba.stackexchange.com/q/86415/57105) với so sánh các cách tiếp cận khác nhau. –

Trả lời

14
SELECT a, b, c 
FROM (
     SELECT *, ROW_NUMBER() OVER (PARTITION BY a ORDER BY b, c) rn 
     FROM mytable 
     ) q 
WHERE rn = 1 
ORDER BY 
     a 

hoặc

SELECT mi.* 
FROM (
     SELECT DISTINCT a 
     FROM mytable 
     ) md 
CROSS APPLY 
     (
     SELECT TOP 1 * 
     FROM mytable mi 
     WHERE mi.a = md.a 
     ORDER BY 
       b, c 
     ) mi 
ORDER BY 
     a 

Tạo một chỉ số tổng hợp trên (a, b, c) cho các truy vấn để làm việc nhanh hơn.

Cách nào hiệu quả hơn phụ thuộc vào phân phối dữ liệu của bạn.

Nếu bạn có vài giá trị riêng biệt a nhưng nhiều bản ghi trong mỗi a, truy vấn thứ hai sẽ tốt hơn.

Bạn có thể cải thiện nó hơn nữa bằng cách tạo ra một cái nhìn được lập chỉ mục:

CREATE VIEW v_mytable_da 
WITH SCHEMABINDING 
AS 
     SELECT a, COUNT_BIG(*) cnt 
     FROM dbo.mytable 
     GROUP BY 
       a 

GO 

CREATE UNIQUE CLUSTERED INDEX 
     pk_vmytableda_a 
ON  v_mytable_da (a) 

GO 

SELECT mi.* 
FROM v_mytable_da md 
CROSS APPLY 
     (
     SELECT TOP 1 * 
     FROM mytable mi 
     WHERE mi.a = md.a 
     ORDER BY 
       b, c 
     ) mi 
ORDER BY 
     a 
+0

Cảm ơn bạn rất nhiều! Yêu câu trả lời đầu tiên của bạn – mezamorphic

+0

Có một vấn đề nhỏ, tôi đang sử dụng mã này là một hàm, trả về một bảng ... nhưng nó sẽ không cho phép tôi bao gồm câu lệnh ORDER BY .... EDIT: Không sao đâu. Tôi đã sử dụng một thủ tục – mezamorphic

+0

@Porcupine: 'ORDER BY' không có ý nghĩa bên trong một hàm. Bạn nên thêm 'ORDER BY' vào cuối truy vấn bằng hàm:' SELECT * FROM myfunction (2) ORDER BY a'. Trình tối ưu hóa sẽ đẩy nó vào truy vấn nếu nó chứng minh hiệu quả. – Quassnoi

0
SELECT * 
FROM 
    (SELECT *, 
      ROW_NUMBER() OVER (PARTITION BY Dealld 
          ORDER BY Price, Dealld) rn 
    FROM DealOffers) q 
WHERE rn = 1 
ORDER BY Name 
+2

Vui lòng chỉnh sửa với nhiều thông tin hơn. Các câu trả lời chỉ có mã và "dùng thử" này không được khuyến khích, bởi vì chúng không chứa nội dung có thể tìm kiếm được và không giải thích tại sao một người nào đó nên "thử cái này". Chúng tôi nỗ lực ở đây để trở thành một nguồn lực cho kiến ​​thức. – abarisone

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