2013-12-09 25 views
6

Câu hỏi quen thuộc, nhưng với Vertica. Tôi muốn trả lại 5 hàng geo_country hàng đầu dựa trên tổng (imps) cho mỗi tag_id. Đây là truy vấn tôi đã bắt đầu:Trả về N hàng đầu cho mỗi nhóm (Vertica/vsql)

SELECT tag_id, 
     geo_country, 
     SUM(imps) AS imps, 
     RANK() OVER (PARTITION BY tag_id ORDER BY SUM(imps) DESC) AS rank 
FROM table1 
WHERE tag_id IN (2013150,1981153) 
AND ymd > CURRENT_DATE - 3 
GROUP BY 1, 
     2 LIMIT 10; 

Điều này thực sự chỉ trả về các hàng từ thẻ đầu tiên trong mệnh đề WHERE (2013150). Tôi biết rằng các thẻ khác có tổng (imps) giá trị đủ cao mà nên bao gồm nó trong các kết quả.

Ngoài ra, làm cách nào để triển khai phần Top N? Tôi đã thử thêm một mệnh đề LIMIT trong hàm OVER, nhưng nó không giống như nó là một tham số được chấp nhận.

Trả lời

9

Đã giải quyết. Giải pháp là để chuyển đổi các truy vấn đến một subquery và sau đó sử dụng mệnh đề WHERE để lọc theo cấp bậc:

SELECT * 
FROM (SELECT tag_id, geo_country, sum(imps), 
    RANK() OVER (PARTITION BY tag_id ORDER BY SUM(imps) DESC) AS rank 
    FROM table1 
    WHERE tag_id IN (2013150,1981153) 
    AND ymd > CURRENT_DATE - 3 
    GROUP BY 1,2) as t2 
WHERE t2.rank <=5; 
+0

Đây là mẫu tôi sử dụng mọi lúc, nhưng không hài lòng vì lý do nào đó. Tôi đoán tôi muốn có một cái gì đó giống như HAVING cho các truy vấn phân tích? – kimbo305

+1

Xem xét chấp nhận câu trả lời của bạn để hoàn thành câu hỏi. – Kermit

+0

@ kimbo305 đó không phải là cách các truy vấn phân tích hoạt động cũng như không tuân thủ các tiêu chuẩn SQL. – Kermit

0

Tôi nghĩ rằng những gì đang xảy ra ở đây là nhóm bởi đơn đặt hàng dữ liệu của bạn trên TAG_ID và sau đó geo_country. Làm một giới hạn sau đó lấy 10 bản ghi đầu tiên. Nếu có ít nhất 10 geo_countries cho tag_id 1 thì bạn sẽ chỉ thấy tag_id 1 trong kết quả của mình. Sẽ không phân loại ASC xếp hạng giải quyết vấn đề của bạn.

Tôi không chắc liệu việc sử dụng xếp hạng trong sắp xếp có được cho phép hay không trong Vertica.

SELECT tag_id, 
    geo_country, 
    SUM(imps) AS imps, 
    RANK() OVER (PARTITION BY tag_id ORDER BY SUM(imps) DESC) AS rank 
FROM table1 
WHERE tag_id IN (2013150,1981153) 
AND ymd > CURRENT_DATE - 3 
GROUP BY 1, 
     2 
ORDER BY 4 
LIMIT 10; 
Các vấn đề liên quan