Đây là một giải pháp hoạt động tổng quát hơn, ngay cả khi các cặp không nhất thiết phải được tìm thấy ngay bên cạnh nhau. (Nếu điều đó trên thực tế là BẮT BUỘC, nếu các bộ phận không thể được ghép nối nếu ID của chúng không liên tiếp, thì điều kiện đó có thể được thêm vào truy vấn.)
with
test_data ( id, lr, identifier ) as (
select '001', 'L', 'B15A' from dual union all
select '002', 'R', 'A15C' from dual union all
select '003', 'L', 'A15C' from dual union all
select '004', 'R', 'A15C' from dual union all
select '005', 'L', 'A15C' from dual union all
select '006', 'R', 'D5A2' from dual union all
select '009', 'R', 'D5A2' from dual union all
select '010', 'L', 'E5A6' from dual union all
select '011', 'R', 'E5A6' from dual union all
select '012', 'L', 'E5A6' from dual union all
select '013', 'R', 'E5A6' from dual union all
select '014', 'R', 'H9S5' from dual union all
select '017', 'L', 'EE5A' from dual union all
select '018', 'R', 'EE5A' from dual
)
-- end of test data, the solution (SQL query) begins below this line
select id, lr, identifier
from ( select id, lr, identifier,
row_number() over (partition by identifier, lr order by id) as rn,
least( count(case when lr = 'L' then 1 end) over (partition by identifier),
count(case when lr = 'R' then 1 end) over (partition by identifier)
) as least_count
from test_data
)
where rn <= least_count
order by id -- ORDER BY is optional
;
Đầu ra :
ID LR IDENTIFIER
--- -- ----------
002 R A15C
003 L A15C
004 R A15C
005 L A15C
010 L E5A6
011 R E5A6
012 L E5A6
013 R E5A6
017 L EE5A
018 R EE5A
10 rows selected
Giải thích:Trong truy vấn bên trong, tôi thêm hai cột nữa vào dữ liệu ban đầu. Một, rn
, đếm riêng biệt (bắt đầu từ 1 và tăng dần 1) cho từng định danh, riêng cho 'L' và 'R'. Điều này sẽ được sử dụng để tạo thành các cặp. Và, ct
đưa ra ít nhất trong tổng số lần đếm cho 'L' và 'R' cho mỗi số nhận dạng. Trong truy vấn bên ngoài, tôi chỉ lọc ra tất cả các hàng có rn > ct
- đó là những hàng không có một cặp trong bảng đầu tiên. Những gì còn lại là các cặp.
ĐÃ THÊM :Với điều kiện bổ sung là một cặp phải được tạo từ các hàng "liên tiếp" (được đo bằng id
cột), đây trở thành một câu hỏi thú vị hơn. Đó là vấn đề về khoảng trống và đảo (xác định các nhóm hàng liên tiếp có cùng đặc điểm), nhưng có một điểm khác biệt:LR
giá trị phải xen kẽ trong nhóm, thay vì không đổi. Phương pháp "tabibitosan" rất hiệu quả không thể được áp dụng ở đây (tôi nghĩ); phương pháp "bắt đầu nhóm", nói chung hơn, hoạt động. Đây là những gì tôi đã sử dụng ở đây. Lưu ý rằng cuối cùng, tôi bỏ đi hàng cuối cùng trong một nhóm, nếu số lượng cho nhóm là một số lẻ. (Chúng tôi có thể tìm thấy hai hoặc bốn hoặc sáu hàng liên tiếp tạo thành một hoặc hai hoặc ba cặp, nhưng không phải là một số lẻ các hàng có LR xen kẽ). Cũng lưu ý rằng nếu hai hàng có cùng số nhận dạng VÀ LR, thì hàng thứ hai sẽ luôn bắt đầu một nhóm MỚI, vì vậy nếu nó trên thực tế là một phần của một cặp (với hàng SAU nó), thì điều đó sẽ được giải pháp này nắm bắt chính xác.
So sánh giải pháp này với giải pháp MATCH_RECOGNIZE dành cho Oracle 12 trở lên mà tôi đã đăng riêng - và đánh giá cao nó đơn giản hơn bao nhiêu!
with
prep ( id, lr, identifier, flag ) as (
select id, lr, identifier,
case when identifier = lag(identifier) over (order by id)
and lr != lag(lr) over (order by id)
then null else 1 end
from test_data -- replace "test_data" with actual table name
),
with_groups ( id, lr, identifier, gp ) as (
select id, lr, identifier,
sum(flag) over (order by id)
from prep
),
with_rn ( id, lr, identifier, rn, ct ) as (
select id, lr, identifier,
row_number() over (partition by identifier, gp order by id),
count(*) over (partition by identifier, gp)
from with_groups
)
select id, lr, identifier
from with_rn
where rn < ct or mod(rn, 2) = 0
order by id -- ORDER BY is optional
;