하위 쿼리에 정확히 하나의 고유 한 결과와 지정된 값이 간결하게 있는지 확인하는 방법은 무엇입니까?


10

나는 다음을 쓰는 것을 발견했다.

select 'yes' 
where exists(select * from foo where val=1)
and not exists(select * from foo where val<>1);

너무 많은 가독성을 희생하지 않고 더 간결한 방법이 있는지 궁금합니다.

답변으로 게시하는 한 가지 방법을 찾았지만 완전히 만족스럽지 않으며 대안에 매우 관심이 있습니다.

이 경우 val내에서 고유합니다 foo-중복이 없습니다


하위 쿼리 결과에서 정확히 하나의 행 을 원한다는 것을 올바르게 이해하고 있습니까?
Erwin Brandstetter

어떤 하위 쿼리?
잭 topanswers.xyz 시도라고

제목에서 언급 한 것. "명확한"이후 또는 그 이전에 하나의 결과 여야하는지 확실하지 않았습니다.
Erwin Brandstetter

아 그래, 하나 :) 내가 오히려 혼동 내에서 하위 쿼리를 참조 것을 대답은 - 당신은 당신은 또한 사용할 수 있습니다 예를 들어, 훨씬 더 구체적이고 유연하다 count(distinct val)내 실제 경우가 더 차이가 없지만,
잭 시도는 말한다 topanswers.xyz 2018 년

답변:


8

간결하고 빠르며 (특히 많은 행으로) 가독성 과 관련하여 내가 가장 좋아하는 것은 속임수와도 작동합니다.

SELECT count(*) = 1 AND min(val) = 1 FROM foo;

반환 TRUE/ FALSE... 나 NULL- 단지 와 정확히 한 행의 경우 val IS NULL, 때문에 count()결코 반환 NULL또는 전혀 행입니다.

1예제 의 두 번째 는 예제 때문에 첫 번째와 동일합니다.


질문의 쿼리가 NULL값으로 실패 합니다. 간단한 데모를 고려하십시오.

CREATE TABLE foo (id int, val int);
INSERT INTO foo VALUES (1, 1),(2, NULL);

SELECT 'yes' 
WHERE      EXISTS(SELECT * FROM foo WHERE val =  1)
AND    NOT EXISTS(SELECT * FROM foo WHERE val <> 1);

IS DISTINCT FROM이 문제를 해결하지만 중복으로 인해 실패 할 수 있습니다 val-이 경우 배제했습니다.


당신의 대답은 잘 작동합니다. 행을
반환 'yes'합니다.

그래도이 짧은 형식을 선호합니다. PostgreSQL (Oracle과 달리)의 boolean유형 이 적절하다는 것을 잊지 마십시오 .

SELECT array_agg(val) = array[1] FROM foo;

TRUE/ FALSE/를 반환합니다 NULL.


우수, 감사, 내가 더 좋은 방법 :이있을 줄 알았습니다
잭 topanswers.xyz 시도라고

5

@Erwin의 답변에 대한 변형. 아니 COUNT()전혀 만 MIN()하고 MAX(). 큰 테이블과 (경우에 따라) 복제가 약간 더 효율적일 수 있습니다 val.

SELECT MIN(val) = 1 AND MAX(val) = 1 FROM foo;

+1 감사합니다. 그것은 널 (null)을 처리하고 (어떤이 있다면) 물론 다른 복제
잭은 말한다 topanswers.xyz 시도

@ 잭 : 예. 테이블에 null이 있습니까? 아니면 두 가지 경우 모두에 대한 답변을 원하십니까?
ypercubeᵀᴹ

어떤 광산하지 않습니다 - 나는 :) 중 하나를 사용할 수 있습니다
잭 topanswers.xyz 시도라고

겠습니까 많은 쿼리 결과를 테스트 할 때처럼 - 더 빨리 더 큰하는 인덱스와 테이블,하지만 수행에 동일하게 같은 인덱스의 부재이다.
Erwin Brandstetter


1

이것은 반환 true, false또는 빈 결과 :

 select j.val is null 
 from foo left join foo as j on j.val <> foo.val 
 where foo.val = 1 limit 1;

언뜻보기 falsefoo어디에 값이 있으면 반환되지 않는 것 같습니다 val<>1.
잭 topanswers.xyz 시도라고

@JackDouglas 아 죄송합니다. 나는 처음에 그 과제를 잘못 이해했다. 결정된.
grayhemp

작동-이 경우 제외 NULL되지 않은 값으로 제외하십시오 .
Erwin Brandstetter

@ErwinBrandstetter NULLIS [NOT] DISTINCT FROM내가 생각 하는 것을 사용하여 해결할 수 있습니다 .
grayhemp

1
@ grayhemp :이 경우에는 아닙니다. 로 시작 LEFT JOIN foo j ON j.val <> foo.val하는 행을 감지하지 못합니다 j.val IS NULL. 그것을 포함 시키 ON j.val IS DISTINCT FROM foo.val려면 j정의 된 다른 열을 확인 NOT NULL하여 두 경우를 구별해야합니다. 그러나 추가 열이 정의되어 있지 않습니다.
Erwin Brandstetter
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.