Như @Milen đã đề cập regexp_matches()
có thể là chức năng sai cho mục đích của bạn. Bạn muốn đơn giản đối sánh cụm từ thông dụng (~
)
. Trên thực tế, toán tử LIKE (~~
)
sẽ nhanh hơn :
Có lẽ là nhanh nhất với LIKE
SELECT msg.message
,msg.src_addr
,msg.dst_addr
,mnc.name
FROM mnc
JOIN msg ON msg.src_addr ~~ ('%38' || mnc.code || '%')
OR msg.dst_addr ~~ ('%38' || mnc.code || '%')
WHERE length(mnc.code) = 3
Ngoài ra, bạn chỉ muốn mnc.code
trong số chính xác 3 ký tự.
Với regexp
Bạn có thể viết tương tự với các biểu thức chính quy nhưng nó chắc chắn sẽ chậm hơn. Đây là một ví dụ hoạt động gần với bản gốc của bạn:
SELECT msg.message
,msg.src_addr
,msg.dst_addr
,mnc.name
FROM mnc
JOIN msg ON (msg.src_addr || '+' || msg.dst_addr) ~ (38 || mnc.code)
AND length(mnc.code) = 3
Điều này cũng yêu cầu msg.src_addr
và msg.dst_addr
là NOT NULL
.
Truy vấn thứ hai trình bày cách kiểm tra bổ sung length(mnc.code) = 3
có thể vào JOIN
điều kiện hoặc một WHERE
mệnh đề. Hiệu ứng tương tự ở đây.
Với regexp_matches ()
Bạn có thể làm cho điều này hoạt động với regexp_matches()
:
SELECT msg.message
,msg.src_addr
,msg.dst_addr
,mnc.name
FROM mnc
JOIN msg ON EXISTS (
SELECT *
FROM regexp_matches(msg.src_addr ||'+'|| msg.dst_addr, '38(...)', 'g') x(y)
WHERE y[1] = mnc.code
)
Nhưng nếu so sánh thì sẽ chậm - hoặc tôi cho là vậy.
Giải thích:
Biểu thức regexp_matches () của bạn chỉ trả về một mảng gồm tất cả các chuỗi con được bắt của đầu tiên cuộc thi đấu. Vì bạn chỉ nắm bắt một chuỗi con (một cặp dấu ngoặc trong mẫu của bạn), bạn sẽ chỉ nhận được mảng có một phần tử .
Bạn nhận được tất cả các kết quả phù hợp với nút chuyển "toàn cầu" bổ sung 'g'
- nhưng ở nhiều hàng. Vì vậy, bạn cần một lựa chọn phụ để kiểm tra tất cả (hoặc tổng hợp). Đặt nó trong EXISTS
- bán tham gia và bạn đến nơi bạn muốn.
Có thể bạn có thể báo cáo lại bằng kiểm tra hiệu suất của cả ba? Sử dụng GIẢI THÍCH PHÂN TÍCH cho điều đó.