2012-11-14 3 views
1

집합의 모든 요소가 열의 행의 일부에 포함되어 있는지 확인하고 싶습니다. 예를 들어,정규식을 사용하여 값 집합과 일치시킬 수 있습니까?

설정 A = {5013, AAB, 402dha)

열 B

 
adaf**5013**dad344 
23**aab**yyyy 
zzz**402dha**vuuuda 
..... 
... 
  1. 내가 사용할 수 없습니다 "여기서 A의 열 B"가 선행 및 후행하기 때문에 문자;
  2. 검색하려는 요소가 열 행의 일부에있을 수 있으므로 TRIM, SUBSTRING을 사용할 수 없습니다.
  3. A가 3 개 요소 만 가질 때 where 절에 3 개의 정규 표현식을 쓸 수 있지만 A가 ~ 1000 개 요소를 가질 때는 할 수 없습니다.

제가 할 수있는 방법이 있다면 저의 질문은 무엇입니까? 아니면 Excel에서 'VLookup'과 유사한 기능이 있습니까?

나는 어떤 생각이라도 고맙게 생각한다!

+7

4. 하나의 열에 여러 값을 저장하지 않도록 데이터 모델을 다시 설계하십시오. –

+0

'A'는 해당 표현식에 나타나지 않습니다. "당신이 썼을 때 **"매 ** "가 아닌, 한 열의 행의 어떤 부분에도 ** 요소가 ** 포함되어 있다면? –

+0

@ user1751221 질문 할 때 설명을 요청하는 댓글에 * 답장하십시오. http://meta.stackexchange.com/questions/19756/how-do-comments-work –

답변

5

그건 꽤 무시 무시한 스키마입니다. 이를 변경하여 최상의 결과를 얻으려면 여러 값을 다음에 저장하십시오.

  • 일반 관계형 하위 테이블;
  • Arrays; 또는
  • 당신이 원하는, 그리고 자식 테이블에 대한 일반 B-tree 인덱스를 통해 (색인, 그리고 GIST 또는 GIN 인덱스를 통해 결정하는 매우 간단하고 제정신 SQL 표현식을 사용할 수 있도록 모두의
  • hstore

배열 및 hstore의 경우) 큰 테이블에서 더 나은 성능을 제공합니다.

분명히 그대로 가능하지만 성능은 비참 할 것입니다. 한 가지 방법은 regexp_split_to_array을 사용하여 열을 배열로 변환 한 다음 array operators을 사용하여 겹침을 테스트하는 것입니다.

확장 테스트 세트를 사용하는 this SQLFiddle demo을 참조하십시오. 사용자가 문제를 설명하기에 충분하지 않았기 때문입니다.

원하는 질문에서 분명하지 않기 때문에 "모든 세트가 열에 나타납니다"(%%)와 "모든 세트가 열에 나타남"(@>)을 보았습니다.


설정 :

CREATE TABLE test(gah text); 

INSERT INTO test(gah) VALUES 
('adaf**5013**dad344'), 
('23**aab**yyyy'), 
('zzz**402dha**vuuuda'), 
('no**matches**here**lalala'), 
('5013**aab**402dha'), 
('402dha**aab**somethingelse**5013'), 
('402dha**aab**5013'); 

데모 :

regress=> SELECT gah FROM test 
      WHERE regexp_split_to_array(gah, '\*\*') && ARRAY['5013', 'aab', '402dha']; 
       gah     
---------------------------------- 
adaf**5013**dad344 
23**aab**yyyy 
zzz**402dha**vuuuda 
5013**aab**402dha 
402dha**aab**somethingelse**5013 
402dha**aab**5013 
(6 rows) 

regress=> SELECT gah FROM test 
      WHERE regexp_split_to_array(gah, '\*\*') @> ARRAY['5013', 'aab', '402dha']; 
       gah     
---------------------------------- 
5013**aab**402dha 
402dha**aab**somethingelse**5013 
402dha**aab**5013 
(3 rows) 

놀랍게도, 당신이 실제로 표현 인덱스의 PostgreSQL의 지원을 사용하여이 쿼리를 도움이됩니다 인덱스를 만들 수 있습니다. 물론, 당신이 그것을 의미하지 않는다 할 수있다해서 그것이 좋은 생각 :

regress=> CREATE INDEX test_glah_resplit_gin ON test 
      USING GIN((regexp_split_to_array(gah, '\*\*'))); 
CREATE INDEX 
regress=> -- Only for testing purposes, don't use in production: 
regress=> SET enable_seqscan = off; 
SET 
regress=> explain SELECT gah FROM test WHERE regexp_split_to_array(gah, '\*\*') @> ARRAY['5013', 'aab', '402dha']; 
              QUERY PLAN           
----------------------------------------------------------------------------------------------- 
Bitmap Heap Scan on test (cost=16.00..20.02 rows=1 width=32) 
    Recheck Cond: (regexp_split_to_array(gah, '\*\*'::text) @> '{5013,aab,402dha}'::text[]) 
    -> Bitmap Index Scan on test_glah_resplit_gin (cost=0.00..16.00 rows=1 width=0) 
     Index Cond: (regexp_split_to_array(gah, '\*\*'::text) @> '{5013,aab,402dha}'::text[]) 
(4 rows) 

regress=> explain SELECT gah FROM test WHERE regexp_split_to_array(gah, '\*\*') && ARRAY['5013', 'aab', '402dha']; 
              QUERY PLAN           
----------------------------------------------------------------------------------------------- 
Bitmap Heap Scan on test (cost=16.00..20.02 rows=1 width=32) 
    Recheck Cond: (regexp_split_to_array(gah, '\*\*'::text) && '{5013,aab,402dha}'::text[]) 
    -> Bitmap Index Scan on test_glah_resplit_gin (cost=0.00..16.00 rows=1 width=0) 
     Index Cond: (regexp_split_to_array(gah, '\*\*'::text) && '{5013,aab,402dha}'::text[]) 
(4 rows) 

GIN 인덱스를 업데이트 할 수 비싸다, 그래서 당신은이 방법을 사용하는 경우는 insert/update에 상당한 성능 가격을 지불 .그것은 일반적인 배열에서도 마찬가지입니다. regexp_split_to_table을 사용하여 즉시 작성하면 조금 더 나빠질 수 있습니다. GIN tipsthe intro to GIN indexes을 참조하십시오.

예를 들어, INSERT INTO test(gah) SELECT 'aaaaabbbbb'||(x::text) FROM generate_series(1,1000000) x;을 사용하여 테스트 테이블에 백만 행을 삽입하려면 GIN 인덱스가있는 위치에서 22 초가 걸렸고, 떨어지면 1.6 초가 걸렸습니다. 그것은 값의 균일 성 때문에 특히 나쁜 경우 일 수 있습니다.

관련 문제