Athena (Presto) の LIKE 検索で文字をエスケープする
こんにちは、 @kz_morita です。
今回は、Athena で LIKE 検索するときに検索したい文字列をエスケープする方法について調べたのでまとめます。
対象のクエリ 以下のようなクエリから % を持つテキストを探し出したいようなユースケースを考えます。
WITHdatasetAS(SELECT*FROM(VALUES'aaa_%aaa','bbbbbb','cccccc@#$%^&*()^cc')ast("text"))SELECT*FROMdataset text aaa_%aaa bbbbbb cccccc@#$%^&*()^cc ESCAPE characterを指定する 普通に検索しようとすると、% が LIKE の Wildcard として予約されているので検索することができません。
そのため、Presto には ESCAPE character を指定する構文が用意されています。 以下は、# を ESCAPE character として使用する例です。
WITHdatasetAS(SELECT*FROM(VALUES'aaa_%aaa','bbbbbb','cccccc@#$%^&*()^cc')ast("text"))SELECT*FROMdatasetWHERE"text"LIKE'%#%%'ESCAPE'#'以下のように正しく実行することができます。
text aaa_%aaa cccccc@#$%^&*()^cc 全記号を検索したいなどの特殊ケース 上記の方法で、大体のケースはカバーできると思いますが例えば、検索したい文字が複数あって他のテーブルに格納されているなどといったケースではもう少し考慮が必要です。
WITHdatasetAS(SELECT*FROM(VALUES'aaa_%aaa','bbbbbb','cccccc@#$%^&*()^cc')ast("text")),symbol_dataAS(SELECTARRAY['!','@','#','$','%','^','&','*','(',')']assymbols),data_with_symbolsAS(SELECT*,(SELECTsymbolsFROMsymbol_dataLIMIT1)assymbolsFROMdataset)SELECT*,filter(symbols,s->"text"LIKE'%'||s||'%')ashitFROMdata_with_symbolsWHEREcardinality(filter(symbols,s->"text"LIKE'%'||s||'%'))>0上記は symbol_data というテーブルに格納されている記号で検索するようなケースを想定しています。
以下の部分は、配列に格納されている記号データを "text" フィールドに含まれているものだけ filter してその件数が 0 件以上という条件を WHERE 句で指定しています。