我想根据某些条件选择一行,但是如果没有行与该条件匹配,我想返回第一行
较短(正确)
你实际上并不需要一个
WHERe条款 都 :
SELECt street, zip, cityFROM addressORDER BY street !~~ 'Test%', ordLIMIT 1;
!~~只是Postgres运算符的
NOT LIKE。您可以使用任何一个。请注意,通过反转逻辑(
NOTLIKE而不是
LIKE),我们现在可以使用默认的
ASC排序顺序和NULL最后排序,这可能很重要。继续阅读。
这更短(但不一定更快)。它也与@Gordon当前接受的答案稍有不同(更可靠)。
在 按boolean
表达式排序时,您必须了解其工作方式:
- 将空值排在所有其他值之后,除非特殊
当前接受的答案使用
ORDER BY <boolean expression> DESC,它将首先对NULL进行排序。在这种情况下,通常应添加
NULLSLAST:
- PostgreSQL按datetime asc排序,是否为null?
如果
street定义
NOT NULL这显然是不相关的,但是这并 没有 在这个问题被定义。( 始终
提供表定义。)当前接受的答案通过在
WHERe子句中排除NULL值来避免此问题。
其他一些RDBMS(MySQL,Oracle等)没有
booleanPostgres之类的适当类型,因此我们经常看到来自那些产品的人的错误建议。
您当前的查询(以及目前公认的答案), 需要 的
WHERe条款-或者至少
NULLS LAST。对于不同的表达,
ORDERBY两者都不是必需的。
更重要的 是,如果多行具有匹配项
street(这是可以预期的),则返回的行将是任意的,并且可能在调用之间发生变化-
通常是不希望有的结果。该查询选择
ord要打破平局的关系最小的行,并产生稳定的结果。
这种形式也更加灵活,因为它不依赖于带有的行的存在
ord = 0。取而代之的
ord是,选择最小的行。
索引更快
(并且仍然正确。)对于大表,以下索引可以从根本上提高此查询的性能:
CREATE INDEX address_street_pattern_ops_idx ON address(street text_pattern_ops);
详细说明:
- PostgreSQL LIKE查询性能差异
根据未定义的详细信息,可能需要向索引中添加更多列。
使用此索引的最快查询:
(SELECt street, zip, cityFROM addressWHERe street LIKE 'Test%'ORDER BY ord -- or something else?-- LIMIT 1 -- you *could* add LIMIT 1 in each leg)UNIOn ALL(SELECt street, zip, cityFROM addressORDER BY ord-- LIMIT 1 -- .. but that's not improving anything in *this* case)LIMIT 1
顺便说一句,这是一个 单一的 声明。
这比较冗长,但允许使用更简单的查询计划。如果第一个产生足够多的行(在我们的示例中为1)
SELECT,
UNIOnALL则永远不会执行第二个
SELECT。如果使用进行测试
EXPLAIN ANALYZE,则会
(never executed)在查询计划中看到。
细节:
- 尝试多个SELECT直到结果可用的方法?
评估 UNIOn ALL
回应戈登的评论。每个文档:
除非括号中另有说明,否则
UNIOn同一SELECT语句中的多个运算符 从左到右 求值 。
大胆强调我的。一旦找到足够的行
,
LIMIT并使Postgres停止评估。这就是为什么您
(never executed)在的输出中看到的原因
EXPLAIN ANALYZE。
如果
ORDER BY在最终之前添加外部,
LIMIT则无法进行优化。然后,必须收集 所有 行以查看可能首先排序的行。



