2012-12-21 3 views
5

Ecco lo scenario. Come utilizzare REGEXP per simulare l'operatore IN fino a corrispondere a tutti i valori nel lato sinistro all'interno del lato destro indipendentemente dall'ordine delle stringhe in entrambi i lati. È possibile ottenere anche la soluzione ANSI SQL utilizzando join sinistro e sottocategorie.REGEXP per abbinare una stringa di gruppo all'interno di un altro elenco di gruppi indipendentemente dall'ordine - SQL

tabella di esempio:

Parent table, Child table, Parent_Child. Per non prendere più spazio sulla domanda, inserisco qui solo un reulst di 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 

Risultato previsto: Selezionare genitore che ha loro tutti i bambini hanno partecipato a qualcosa.

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

ecco la soluzione REGEXP SQL: ora il problema qui, non restituisce risultati corretti se l'ordine lato sinistro/squence non corrisponde lato destro.

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 
; 

Quindi ci sono due aspetti Apprezzerei per la domanda:

  1. Qual è il modello migliore per abbinare tutti i nomi a sinistra per l'elenco definito dall'utente del diritto lato indipendentemente dall'ordine?
  2. Quale potrebbe essere la prestazione ottenuta utilizzando REGEXP?
+0

Il vero problema qui è che i bambini non dovrebbero essere una colonna separata da virgola, ma dovrebbero essere una tabella di dettaglio. Vedi questa domanda: [La memorizzazione di un elenco delimitato in una colonna di database è davvero così brutta?] (Http://stackoverflow.com/questions/3653462/is-storing-a-delimited-list-in-a-database-column- davvero-che-male) –

risposta

2

Si desidera utilizzare regexp o un'altra soluzione va bene lo stesso? Se ho capito bene, questa query dovrebbe darvi il risultato corretto:

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 

che dà:

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

In ogni caso, per utilizzare la soluzione, vi suggerisco di utilizzare group_concat con un ordine:

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 

e cercare di abbinare i nomi già ordinati. Questo è identico alla query, ho aggiunto solo uno order by c.name all'interno di group_concat e ho anche ordinato la stringa nella condizione where.

Edit: Se davvero si vuole utilizzare un REGEXP, dal momento che il supporto MySql per le espressioni regolari è limitato, vorrei suggerire di provare a utilizzare LIB_MYSQLUDF_PREG. Questa è una soluzione generale che non funziona con le espressioni regolari standard di MySql.

Se è necessario abbinare una stringa come questa:

One,Two,Three,Four 

con, per esempio, questo:

Two,Four,Three,One 

è necessario utilizzare un'espressione regolare come questo:

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

(check this question) E questo è quello che fa:

  1. \bTwo\b partite piene parola di due, possono essere: TwoTwo,,Two,Two,
  2. .* parola Due si trovano ovunque nella stringa .*\bTwo\b
  3. (?=.*\bTwo\b) partita piena parola Due, in qualsiasi punto della stringa, ma dimentica la posizione e iniziare a mach il prossimo mandato dall'inizio
  4. inizio per abbinare altre parole

Manca ancora qualcosa? Sì, perché se abbiamo una corrispondenza per "One,Two,Three,Four", corrisponderà anche a "One,Two,Three,Four,Five". Forse c'è una regexp migliore per questo, ma la mia idea è: se corrispondono, e hanno la stessa lunghezza, devono essere identici tranne che per l'ordine. Così possiamo aggiungere questo alla fine della nostra regexp:

  1. .{length}$ ricordare che, dopo tutte le partite precedenti, siamo ancora agli inizi, e ^.{length}$ corrisponde a una stringa di lunghezza data

codice Quindi finale sarebbe:

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

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

si noti che questa regexp non è supportato da rEGEXP, si deve essere supportato su LIB_MYSQLUDF_PREG, ma non ho ancora testato. Le farò sapere. Potrebbero esserci altre soluzioni, ma non penso che sia possibile fare di meglio con solo REGEXP.

+0

Grazie per lo sforzo. Ho già due query che mi danno la risposta senza 'regexp'. Infatti uno è esattamente la stessa della prima query. Quindi, la ragione principale per cui ho posto la domanda per ottenere la risposta, la soluzione basata su 'regexp' :-) forse ho bisogno di sottolineare ulteriormente che sulla mia domanda. Sono più curioso di conoscere le prestazioni tra due metodi diversi. – bonCodigo

+0

@bonCodigo non ero sicuro che fosse necessario ... l'idea di usare solo regexp è bella .. non ho ancora una risposta, ma ci penserò :) +1 per la domanda – fthiella

+0

molto apprezzato ogni infor efficace verso la soluzione 'regexp' :) :) Infatti ho già controllato uno dei post precedenti a cui avevi risposto. [Riferimento] (http: // StackOverflow.it/questions/10480568/valori separati da virgola-in-mysql-in-clausola/13445491 # 13445491) – bonCodigo

Problemi correlati