如何检查子查询是否恰好具有一个完全不同的结果和一个指定的值?


10

我发现自己写了以下内容:

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

并且想知道是否有一种更简洁的方法而不牺牲太多的可读性。

我找到了一种发布答案的方法,但我对此并不完全满意,并且会对替代方法非常感兴趣

在这种情况下val,内部是唯一的foo-没有重复项


我是否正确理解你想要的是一个子查询的结果行?
— Erwin Brandstetter 2012年


您在标题中提到的那个。我不确定这应该是“与众不同”之后还是之前的结果。
— Erwin Brandstetter 2012年

是的,那是一个:)我在回答中的子查询时相当混乱-您的子查询更加具体和灵活,例如,您也可以使用count(distinct val),尽管在我的实际案例中这没什么关系
— 杰克说尝试topanswers.xyz 2012年

Answers:


8

简洁,快速(特别是有很多行),我最喜欢的是可读性,并且也可以与dupes一起使用:

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。



5

@Erwin答案的变化形式。完全没有COUNT(),只有MIN()和MAX()。大表和(不是您的情况下)重复表可能会更有效val:

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

+1谢谢。当然,它对null和重复项的处理方式也有所不同(如果有的话)
— 杰克说请尝试topanswers.xyz 2012年

@杰克:是的。您的表格是否有空值?还是您想针对这两种情况(有或没有)都给出答案?
— ypercubeᵀᴹ

没有我不会-我可以使用:)
— 杰克说尝试topanswers.xyz 2012年

将是多快于与匹配的索引更大的表,但执行相同的在不存在这样的索引-测试查询结果时等。
— Erwin Brandstetter,2012年


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;

乍一看,false如果foowhere中有值,这似乎不会返回val<>1。
— 杰克说请尝试topanswers.xyz 2012年

@JackDouglas哦,对不起。我第一次错了任务。固定。
— grayhemp 2012年

有效-除非具有NULL在这种情况下不排除的值。
— Erwin Brandstetter,2012年

我认为@ErwinBrandstetter NULL可以解决IS [NOT] DISTINCT FROM。
— grayhemp 2012年

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,2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.