2013-09-25 22 views
12

Tôi muốn thực hiện thao tác DISTINCT trên một tập con của các cột. Các documentation nói điều này là có thể với một forested lồng nhau:Làm thế nào để thực hiện một DISTINCT trong Pig Latin trên một tập con của các cột?

Bạn không thể sử dụng DISTINCT trên một nhóm nhỏ các trường; để làm điều này, sử dụng FOREACH và một khối lồng nhau để chọn các trường đầu tiên và sau đó áp dụng DISTINCT (xem Ví dụ: Khối lồng nhau).

Nó là đơn giản để thực hiện một hoạt động riêng biệt trên tất cả các cột:

A = LOAD 'data' AS (a1,a2,a3,a4); 
A_unique = DISTINCT A; 

Cho phép nói rằng tôi đang quan tâm trong việc thực hiện khác nhau trên khắp a1, a2, và a3. Bất cứ ai có thể cung cấp một ví dụ cho thấy làm thế nào để thực hiện hoạt động này với một forested lồng nhau như đề xuất trong tài liệu?

Dưới đây là một ví dụ về đầu vào và đầu ra mong đợi:

A = LOAD 'data' AS(a1,a2,a3,a4); 
DUMP A; 

(1 2 3 4) 
(1 2 3 4) 
(1 2 3 5) 
(1 2 4 4) 

-- insert DISTINCT operation on a1,a2,a3 here: 
-- ... 

DUMP A_unique; 

(1 2 3 4) 
(1 2 4 4) 
+2

Bạn có thể cung cấp đầu vào ví dụ và đầu ra dự kiến ​​không? – zero323

+0

Đề xuất hay, tôi đã cập nhật câu hỏi. – Freerobots

Trả lời

18

Nhóm trên tất cả các cột khác, dự án chỉ là cột quan tâm vào một túi, và sau đó sử dụng FLATTEN để mở rộng lại chúng:

A_unique = 
    FOREACH (GROUP A BY a4) { 
     b = A.(a1,a2,a3); 
     s = DISTINCT b; 
     GENERATE FLATTEN(s), group AS a4; 
    }; 
+0

Ví dụ rất hay! Cảm ơn đã giúp đỡ. Điều này thực sự tương tự như câu trả lời của tôi bằng cách sử dụng riêng biệt, nhưng ngắn gọn hơn nhiều. – Freerobots

+0

cách chúng tôi có thể bật mệnh đề song song trên đó. Tôi đã thử bằng cách sử dụng DEFAULT_PARALLEL 512 trong kịch bản của tôi nhưng điều đó không làm việc và #of reducers không giới hạn ở 512. Bất kỳ đề xuất? – TopCoder

0

Dưới đây là 2 giải pháp khả thi, được có bất kỳ phương pháp tốt khác?

Giải pháp 1 (sử dụng LIMIT 1):

A = LOAD 'test_data' AS (a1,a2,a3,a4); 

-- Combine the columns that I want to perform the distinct across into a tuple 
A2 = FOREACH A GENERATE TOTUPLE(a1,a2,a3) AS combined, a4 as a4 

-- Group by the combined column 
grouped_by_a4 = GROUP A2 BY combined; 

grouped_and_distinct = FOREACH grouped_by_a4 { 
     single = LIMIT A2 1; 
     GENERATE FLATTEN(single); 
}; 

Giải pháp 2 (sử dụng DISTINCT):

A = LOAD 'test_data' AS (a1,a2,a3,a4); 

-- Combine the columns that I want to perform the distinct across into a tuple 
A2 = FOREACH A GENERATE TOTUPLE(a1,a2,a3) AS combined, a4 as a4 

-- Group by the other columns (those I don't want the distinct applied to) 
grouped_by_a4 = GROUP A2 BY a4; 

-- Perform the distinct on a projection of combined and flatten 
grouped_and_distinct = FOREACH grouped_by_a4 { 
     combined_unique = DISTINCT A2.combined; 
     GENERATE FLATTEN(combined_unique); 
}; 
+0

Các giải pháp này không tương đương. Cái đầu tiên sẽ chỉ cung cấp cho bạn hai bộ dữ liệu, vì chỉ có hai kết hợp duy nhất của 'a1',' a2' và 'a3', và giá trị của 'a4' không thể dự đoán được. Thứ hai sẽ cho đầu ra phù hợp với đầu ra mẫu của bạn. (Tuy nhiên, nó không ngắn gọn như nó có thể.) –

1

Dành riêng cho bạn đầu vào/đầu ra, các công trình sau đây. Bạn có thể cập nhật các vectơ thử nghiệm của mình để làm rõ những gì bạn cần khác với điều này.

A_unique = DISTINCT A; 
+0

Vâng có thể giúp :). Tôi đã cập nhật kết quả mong đợi trong câu hỏi ban đầu. – Freerobots

2

Câu trả lời được chấp nhận là một giải pháp tuyệt vời nhưng, trong trường hợp bạn muốn sắp xếp lại các trường trong đầu ra (điều mà tôi đã phải làm gần đây) điều này có thể không hoạt động. Dưới đây là một thay thế:

A = LOAD '$input' AS (f1, f2, f3, f4, f5); 
GP = GROUP A BY (f1, f2, f3); 
OUTPUT = FOREACH GP GENERATE 
    group.f1, group.f2, f4, f5, group.f3 ; 

Khi bạn nhóm trên một số trường nhất định, lựa chọn sẽ có giá trị duy nhất cho nhóm trong mỗi bộ.

0
unique_A = FOREACH (GROUP A BY (a1, a2, a3)) { 
    limit_a = LIMIT A 1; 
    GENERATE FLATTEN(limit_a) AS (a1,a2,a3,a4); 
}; 
Các vấn đề liên quan