2014-02-28 5 views
7

Ich habe eine Spalte mit einem Array von Autoren. Wie kann ich den Operator ~* verwenden, um zu überprüfen, ob einer seiner Werte mit einem bestimmten regulären Ausdruck übereinstimmt?Wie regulärer Ausdruck mit ANY Array-Operator verwendet werden

Der Operator ~* verwendet eine Zeichenfolge, die auf der linken Seite und der reguläre Ausdruck auf der rechten Seite überprüft wird. Die Dokumentation sagt der ANY Operator auf der rechten Seite sein muss, so offensichtlich

`

SELECT '^p' ~* ANY(authors) FROM book; 

`

funktioniert nicht wie PostgreSQL die Zeichenfolge ^p gegen Ausdrücke in der Anordnung enthalten sind, zu entsprechen versucht .

Irgendeine Idee?

+1

Sie sollten Ihre Daten normalisieren, so dass Sie kein "Array" in einer einzelnen Spalte haben. –

+0

Denkbar ... Ich brauche/will keine Tabelle für Autoren pflegen. Es könnten jedoch Telefonnummern sein. – greg

+0

Nun, ob Sie * eine separate Tabelle pflegen wollen oder nicht, genau deshalb sagen alle dazu. Das Durchsuchen einer Liste innerhalb einer einzelnen Spalte wird immer früher oder später unübersichtlich. –

Antwort

7

Die erste offensichtliche Idee ist, Ihren eigenen regexp-Matching-Operator mit vertauschtem Argumenten zu verwenden:

create function commuted_regexp_match(text,text) returns bool as 
'select $2 ~* $1;' 
language sql; 

create operator [email protected]# (
procedure=commuted_regexp_match(text,text), 
leftarg=text, rightarg=text 
); 

Dann können Sie es wie folgt verwendet werden:

SELECT '^p' [email protected]# ANY(authors) FROM book; 

Eine weitere andere Art von Betrachten Sie es, um das Array zu vereinheitlichen und das Äquivalent des ANY-Konstrukts in SQL zu formulieren:

select bool_or(r) from 
    (select author ~* '^j' as r 
    from (select unnest(authors) as author from book) s1 
) s2; 
1

Sie können Ihren eigenen Operator definieren, um das zu tun, was Sie wollen.

die Reihenfolge der Argumente umkehren und die entsprechende Funktion aufrufen:

create function revreg (text, text) returns boolean 
language sql immutable 
as $$ select texticregexeq($2,$1); $$; 

(revreg ... Sie bitte Ihre Lieblingsnamen wählen).

Fügen Sie einen neuen Betreiber unsere revreg() -Funktion:

CREATE OPERATOR ### (
    PROCEDURE = revreg, 
    LEFTARG = text, 
    RIGHTARG = text 
); 

Test:

test=# SELECT '^p' ### ANY(ARRAY['ika', 'pchu']); 
    t 
test=# SELECT '^p' ### ANY(ARRAY['ika', 'chu']); 
    f 
test=# SELECT '^p' ### ANY(ARRAY['pika', 'pchu']); 
    t 
test=# SELECT '^p' ### ANY(ARRAY['pika', 'chu']); 
    t 

Beachten Sie, dass Klauseln an den neuen Betreiber JOIN und RESTICT setzen möchten, um den Planer zu helfen .

1

Ich benutze diese:

create or replace function regexp_match_array(a text[], regexp text) 
returns boolean 
strict immutable 
language sql as $_$ 
select exists (select * from unnest(a) as x where x ~ regexp); 
$_$; 

comment on function regexp_match_array(text[], text) is 
    'returns TRUE if any element of a matches regexp'; 

create operator ~ (
procedure=regexp_match_array, 
leftarg=text[], rightarg=text 
); 

comment on operator ~(text[], text) is 
    'returns TRUE if any element of ARRAY (left) matches REGEXP (right); think ANY(ARRAY) ~ REGEXP'; 

es dann, wie Sie verwenden viel ~ mit Text Skalare verwenden würde:

=> select distinct gl from x where gl ~ 'SH' and array_length(gl,1) < 7; 
┌──────────────────────────────────────┐ 
│     gl     │ 
├──────────────────────────────────────┤ 
│ {MSH6}        │ 
│ {EPCAM,MLH1,MSH2,MSH6,PMS2}   │ 
│ {SH3TC2}        │ 
│ {SHOC2}        │ 
│ {BRAF,KRAS,MAP2K1,MAP2K2,SHOC2,SOS1} │ 
│ {MSH2}        │ 
└──────────────────────────────────────┘ 
(6 rows) 
1

Meine Lösung

SELECT a.* FROM books a 
CROSS JOIN LATERAL (
    SELECT author 
    FROM unnest(authors) author 
    WHERE author ~ E'p$' 
    LIMIT 1 
)b; 

Verwendung Quer seitlich verbinden, Unterabfrage wird für jede Zeile der Tabelle "Bücher" ausgewertet, wenn eine der Zeilen, die von unnest zurückgegeben werden, die Bedingung erfüllt, gibt die Unterabfrage o zurück ne Reihe (wegen Limit).

1
SELECT * FROM book where EXISTS (SELECT * from unnest(author) as X where x ~* '^p') 
+3

Es ist immer gut zu versuchen, Ihren Code zu erklären. – Bugs