2017-11-29 1 views
0

수동으로 입력 한 텍스트를 다른 테이블의 항목 식별자로 참조하는 테이블의 항목을 식별하려고합니다. 데이터 구조는 잘못 설계되어 테이블 간의 간단한 조인에 사용할 항목이 없습니다. 그들은 일치하지 않습니다.PostgreSQL에서 널 검사를 수행하기 위해 서브 쿼리 반복 방지하기

그것은 단지 매우 즐거운 아니에요 나는이 있고 그것을 작동 :

SELECT i.id, (
    SELECT c.text 
    FROM charges c 
    WHERE c.text LIKE CONCAT('%', i.order, '%') 
    AND c.state = 'paid' 
) AS "charge text" 
FROM items i 
WHERE i.state = 'not paid' 
AND (
    SELECT c.text 
    FROM charges c 
    WHERE c.text LIKE CONCAT('%', i.order, '%') 
    AND c.state = 'paid' 
) IS NOT NULL 
ORDER BY id 

예 데이터 charges에서 :

id state text 
------------------------------------------ 
1  paid  Lorem ipsum ABC123 sit amet 
2  not paid DEF456 lorem ipsum sit amet 

예 데이터 items에서 :

id state order 
--------------------- 
1  not paid ABC123 
2  not paid DEF456 

현재 하위 쿼리의 두 번째 인스턴스에서 인스턴스를 제거하려면 NULL이 필요합니다. 이유는 모든 i.number을 검토 한 결과로 선정되었습니다. 하위 쿼리를 두 번 나타나지 않도록하고 싶습니다만, (this answer에서와 같이 WITH)을 사용할 수있는 것으로 나타나지 않습니다. 처음에 정의되어 있으므로 i.number을 전달할 수 없기 때문입니다. 이전에 CTE를 사용하지 않았기 때문에 나는 이것에 대해 틀릴 수도 있습니다.

두 가지 질문이 있습니다. 첫 번째로 하위 쿼리를 한 번 정의한 다음 NOT NULL로 결과를 확인하십시오. 둘째로, 나는이 잘못을 저질렀다. 그리고 그 수표에 대한 필요성을 없애는 더 좋은 방법이있다.

+0

왜 'join'을 사용할 수있을 때 상관 하위 쿼리가 필요합니까? –

+0

안녕히 계십시오 - 말씀해주십시오. 나는 대답으로 그다지 많은 것을 얻지 못한다. –

+0

@ Scott : 묵시적 대답은 "하지 않는다"입니다. – cHao

답변

2

쓰기이 제대로 조인한다. 상관 관계가있는 하위 쿼리는 결과 집합에서 하위 쿼리의 결과가 필요없는 경우에 가장 적합합니다.

SELECT 
    i.id, 
    c.txt 
FROM items i 
    INNER JOIN charges c ON 
     c.text like CONCAT('%', i.order , '%') 
WHERE 
    c.state = 'paid' 
    AND i.state = 'unpaid' 

당신은 그 절에 AND c.txt IS NOT NULL를 추가 할 수 있지만, 내부 조인으로 이미 자신을 참여에 의해 억제되지 않는 것을 잡으려고 아마 확률이 낮다 : 당신이이 경우에, 그래서 그냥 가입 할 수 있습니다.

또한 기본 쿼리 자체에서 수행 할 수없는 다른 논리를 집계하거나 수행하지 않으므로 하위 쿼리를 사용하지 않았습니다.

+0

OK - 완벽합니다. 내 문제는 여기에 가입 할 수 있다는 것을 모르는 것이 었습니다. 고맙습니다. –

+1

그건 의미가 있습니다! 당신은 당신의 JOIN에서 꽤 미쳐있을 수 있습니다. LIKE로는 매우 빠르지는 않지만 일을 끝내게됩니다. 상관 관계가있는 부질의는 결국 JOIN과 똑같이 행동 할 것입니다. 그래서 6의 1, 6의 다른 것입니다. – JNevill

0

일반적으로 당신은 LATERAL JOIN을 사용할 수

SELECT i.id, sub."charge text" 
FROM items i 
LEFT JOIN LATERAL 
(
    SELECT c.text AS "charge text" 
    FROM charges c 
    WHERE c.text LIKE CONCAT('%', i.order, '%') 
    AND c.state = 'paid' 
) sub ON true 
WHERE i.state = 'not paid' 
AND sub."charge text" IS NOT NULL 
ORDER BY id; 

SELECT i.id, sub."charge text" 
FROM items i 
JOIN LATERAL 
(
    SELECT c.text AS "charge text" 
    FROM charges c 
    WHERE c.text LIKE CONCAT('%', i.order, '%') 
    AND c.state = 'paid' 
) sub ON true 
WHERE i.state = 'not paid' 
ORDER BY id; 
관련 문제