2012-12-21 36 views
5

Đây là kịch bản. Cách sử dụng REGEXP để mô phỏng toán tử IN chưa đến khớp với tất cả các giá trị ở phía bên trái bên phải bất kể thứ tự chuỗi ở hai bên. Ngoài ra, giải pháp ANSI SQL có thể đạt được bằng cách sử dụng các truy vấn bên trái và phụ.REGEXP để khớp với một chuỗi nhóm trong một danh sách nhóm khác bất kể thứ tự - SQL

bảng mẫu:

Parent table, Child table, Parent_Child. Để không chiếm nhiều không gian hơn trong câu hỏi, tôi chỉ đăng ở đây một lần nữa là Group_Concat Child query by Parent.

PID  NAME  CHILDREN  
1  dad john dave,jill,lina 
2  mum sandy maryam,jack 
3  dad frank henry,jill 
4  mum kate maryam 
5  mum jean dave 

Dự kiến ​​kết quả: Chọn Chánh người có tất cả con cái của họ tham gia vào một cái gì đó.

PID  NAME  CHILDRENREXGEX 
3  dad frank jill,henry 
4  mum kate maryam 
5  mum jean dave 

Đây là giải pháp SQL REGEXP: bây giờ là vấn đề ở đây, nó không trả về kết quả chính xác nếu bên trái/thứ tự không phù hợp với bên phải.

Query:

select 
    x.pid, x.name, x.children as childrenRexgex 
from 
    (select 
     p.pid, p.name, group_concat(c.name) as children 
    from 
     parent as p 
    inner join 
     parent_child as pc on p.pid = pc.pid 
    join 
     child as c on pc.cid = c.cid 
    group by 
     p.pid 
    order by 
     c.name) as x 
where 
    'dave,maryam,jill,henry' REGEXP x.children 
; 

Do đó có hai khía cạnh tôi sẽ đánh giá cao cho câu hỏi:

  1. mô hình tốt nhất để phù hợp với tất cả các tên ở bên trái để người dùng định nghĩa danh sách bên phải là gì bên bất kể thứ tự?
  2. Hiệu suất có thể đạt được bằng cách sử dụng REGEXP là gì?
+0

Vấn đề thực sự ở đây là trẻ em không nên là cột được phân cách bằng dấu phẩy, nhưng phải là một bảng chi tiết. Xem câu hỏi này: [Lưu trữ một danh sách phân tách trong một cột cơ sở dữ liệu thực sự là xấu?] (Http://stackoverflow.com/questions/3653462/is-storing-a-delimited-list-in-a-database-column- thực sự-đó-xấu) –

Trả lời

2

Bạn có muốn sử dụng regexp hay giải pháp khác không? Nếu tôi hiểu đúng, truy vấn này sẽ cho bạn kết quả chính xác:

select p.pid, parent.name, group_concat(child.name) 
from 
    (select pid 
    from 
    parent_child inner join child 
    on parent_child.cid = child.cid 
    group by pid 
    having sum(child.name in ('dave','henry','maryam','jill'))=count(*)) p 
    inner join parent on p.pid=parent.pid 
    inner join parent_child on p.pid=parent_child.pid 
    inner join child on parent_child.cid=child.cid 
group by p.pid 

cung cấp cho:

PID  NAME  CHILDRENREXGEX 
3  dad frank jill,henry 
4  mum kate maryam 
5  mum jean dave 

Dù sao, sử dụng giải pháp của bạn, tôi sẽ đề nghị bạn sử dụng group_concat với lệnh:

select 
    x.pid, 
    x.name, 
    x.children as childrenRexgex 
from(
    select 
    p.pid, 
    p.name, 
    group_concat(c.name order by c.name) as children, 
    count(c.name) as counts 
    from 
    parent as p inner join parent_child as pc 
    on p.pid = pc.pid 
    join child as c 
    on pc.cid = c.cid 
    group by p.pid) as x 
where 'dave,henry,jill,maryam' 
    REGEXP x.children 

và cố gắng khớp với tên đã được đặt hàng. Điều này giống hệt với truy vấn của bạn, tôi chỉ thêm một order by c.name bên trong group_concat và tôi cũng đã ra lệnh cho chuỗi trong điều kiện vị trí.

Chỉnh sửa: Nếu bạn thực sự muốn sử dụng REGEXP, vì hỗ trợ MySql cho biểu thức chính quy bị giới hạn, tôi khuyên bạn nên thử sử dụng LIB_MYSQLUDF_PREG. Đây là một giải pháp chung không hoạt động với các biểu thức chính quy chuẩn của MySql.

Nếu bạn cần phải phù hợp với một chuỗi như thế này:

One,Two,Three,Four 

với, ví dụ, điều này:

Two,Four,Three,One 

bạn phải sử dụng một regexp như thế này:

"One,Two,Three,Four" REGEXP 
"^(?=.*\bTwo\b)(?=.*\bFour\b)(?=.*\bThree\b)(?=.*\bOne\b)" 

(check this question) Và đây là những gì nó làm:

  1. \bTwo\b trận đấu đầy đủ chữ Hai, có thể là: TwoTwo,,Two,Two,
  2. .* từ Hai có thể tìm thấy ở bất cứ đâu trong chuỗi .*\bTwo\b
  3. (?=.*\bTwo\b) trận đấu đầy đủ chữ Hai, bất cứ nơi nào trong chuỗi, nhưng quên vị trí và bắt đầu mach từ tiếp theo từ đầu
  4. bắt đầu khớp với các từ khác

Vẫn còn thiếu thứ gì đó? Có, bởi vì nếu chúng tôi có kết quả phù hợp cho "One,Two,Three,Four", cũng "One,Two,Three,Four,Five" sẽ khớp. Có lẽ có một regexp tốt hơn cho điều này, nhưng ý tưởng của tôi là: nếu chúng phù hợp, và có cùng độ dài, chúng phải giống hệt nhau ngoại trừ thứ tự. Vì vậy, chúng ta có thể thêm này vào cuối regexp của chúng tôi:

  1. .{length}$ nhớ rằng sau khi tất cả các trận đấu trước đó, chúng tôi vẫn là ngay từ đầu, và ^.{length}$ phù hợp với một chuỗi có độ dài cho

đang Vậy cuối cùng sẽ là:

field1="One,Two,Three,Four" 
field2="Two,Four,Three,One" 

field1 REGEXP CONCAT("^(?=.*\b", 
        REPLACE(field2, ",", "\b)(?=.*\b"), 
        "\b).{", LENGTH(field1), "}$") 

ý rằng regexp này không được hỗ trợ bởi BTCQ, cần được hỗ trợ trên LIB_MYSQLUDF_PREG nhưng tôi vẫn chưa thử nghiệm nó. Tôi sẽ cho bạn biết. Có thể có các giải pháp khác, nhưng tôi không nghĩ rằng nó có thể làm tốt hơn với chỉ REGEXP.

+0

Cảm ơn những nỗ lực. Tôi đã có hai truy vấn cho tôi câu trả lời mà không có 'regexp'. Infact một là chính xác giống như truy vấn đầu tiên của bạn. Vì vậy, lý do chính tôi đăng câu hỏi để có được câu trả lời, giải pháp dựa trên 'regexp' :-) có lẽ tôi cần phải nhấn mạnh thêm rằng về câu hỏi của tôi. Tôi tò mò muốn biết hiệu suất giữa hai phương pháp khác nhau. – bonCodigo

+0

@bonCodigo tôi đã không chắc chắn đây là bạn cần ... ý tưởng sử dụng chỉ regexp là tốt đẹp .. tôi chưa có câu trả lời, nhưng tôi sẽ nghĩ về nó :) +1 cho câu hỏi – fthiella

+0

nhiều đánh giá cao bất kỳ infor hiệu quả đối với giải pháp 'regexp' :) Tôi infact đã kiểm tra một trong những bài viết trước đó, nơi bạn đã trả lời. [Tham khảo] (http: // stackoverflow.com/questions/10480568/dấu phẩy-giá trị-in-mysql-in-khoản/13445491 # 13445491) – bonCodigo

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