当前位置: 首页 > 面试题库 >

如果没有匹配项,则选择第一条记录

齐承运
2023-03-14
问题内容

在PostgreSQL中,我想根据某些条件选择一行,但是如果没有行与该条件匹配,则我想返回第一行。该表实际上包含一个序数列,因此该任务应该更容易(第一行是序数为0的那一行)。例如:

SELECT street, zip, city
FROM address
WHERE street LIKE 'Test%' OR ord = 0
LIMIT 1;

但是在这种情况下,无法保证匹配记录的顺序,因此我无法对其进行排序。使用单个SELECT语句执行此操作的方式是什么?


问题答案:

我想根据某些条件选择一行,但是如果没有行与该条件匹配,我想返回第一行

较短(正确)

你实际上并不需要一个WHERE条款

SELECT street, zip, city
FROM   address
ORDER  BY street !~~ 'Test%', ord
LIMIT  1;

!~~只是Postgres运算符的NOT LIKE。您可以使用任何一个。请注意,通过反转逻辑(NOT LIKE而不是LIKE),我们现在可以使用默认的ASC排序顺序和NULL最后排序,这可能很重要。继续阅读。

这更短(但不一定更快)。它也与@Gordon当前接受的答案稍有不同(更可靠)。

boolean表达式排序时,您必须了解其工作方式:

  • 将空值排在所有其他值之后,除非特殊

当前接受的答案使用ORDER BY <boolean expression> DESC,它将首先对NULL进行排序。在这种情况下,通常应添加NULLS LAST

  • PostgreSQL按datetime asc排序,是否为null?

如果street定义NOT NULL这显然是不相关的,但是这并 没有 在这个问题被定义。( 始终
提供表定义。)当前接受的答案通过在WHERE子句中排除NULL值来避免此问题。

其他一些RDBMS(MySQL,Oracle等)没有booleanPostgres之类的适当类型,因此我们经常看到来自那些产品的人的错误建议。

您当前的查询(以及目前公认的答案), 需要WHERE条款-或者至少NULLS LAST。对于不同的表达,ORDER BY两者都不是必需的。

更重要的 是,如果多行具有匹配项street(这是可以预期的),则返回的行将是任意的,并且可能在调用之间发生变化-
通常是不希望有的结果。该查询选择ord要打破平局的关系最小的行,并产生稳定的结果。

这种形式也更加灵活,因为它不依赖于带有的行的存在ord = 0。取而代之的ord是,选择最小的行。

索引更快

(并且仍然正确。)对于大表,以下索引可以从根本上提高此查询的性能:

CREATE INDEX address_street_pattern_ops_idx ON address(street text_pattern_ops);

详细说明:

  • PostgreSQL LIKE查询性能差异

根据未定义的详细信息,可能需要向索引中添加更多列。
使用此索引的最快查询:

(
SELECT street, zip, city
FROM   address
WHERE  street LIKE 'Test%'
ORDER  BY ord  -- or something else?
-- LIMIT 1  -- you *could* add LIMIT 1 in each leg
)
UNION ALL
(
SELECT street, zip, city
FROM   address
ORDER  BY ord
-- LIMIT 1  -- .. but that's not improving anything in *this* case
)
LIMIT  1

顺便说一句,这是一个 单一的 声明。

这比较冗长,但允许使用更简单的查询计划。如果第一个产生足够多的行(在我们的示例中为1)SELECTUNION ALL则永远不会执行第二个SELECT。如果使用进行测试EXPLAIN ANALYZE,则会(never executed)在查询计划中看到。

细节:

  • 尝试多个SELECT直到结果可用的方法?

评估 UNION ALL

回应戈登的评论。每个文档:

除非括号中另有说明,否则UNION同一SELECT语句中的多个运算符 从左到右 求值 。

大胆强调我的。一旦找到足够的行
LIMIT并使Postgres停止评估。这就是为什么您(never executed)在的输出中看到的原因EXPLAIN ANALYZE

如果ORDER BY在最终之前添加外部,LIMIT则无法进行优化。然后,必须收集 所有 行以查看可能首先排序的行。



 类似资料:
  • 我有两个表客户和订单,下面是结构。 表-客户 ID customer_name 表-订单 ID order_id customer_id customers表包含customers记录,orders表包含客户下的订单, orders表中的customer_id链接到customers表的id字段。 现在一个客户可以有零或一个或多个订单,我想要得到客户下的最后一个订单只。 当我运行以下查询(一个简单

  • 我有两张桌子: Product\u表 Productbreak\u表 我的目标是只获取不在productbreak_table的和日期之间的产品 结果应该是:

  • 问题内容: 我正在尝试匹配模式: 以下仅匹配第一次出现的情况: 结果是: 但是,[使用pythex似乎可以正常工作](http://pythex.org/?regex=%3C–(%5B%5Cw%5Cs%5D%2B)–%3E(%5B%5Cs%5CS%5D*%3F)(%3F%3D%5Cn%3C–%7C%24)&test_string=%3C–%20Option%201%20–%3E%0ANice%20

  • 问题内容: 假设以下单词顺序 我想做的是将文本从BLA提取到LOOK,但是最接近外观的BLA。即我想得到 我应该如何使用正则表达式呢?我得到了一个可行的解决方案,但是效率极低。 有没有更好,更高效的方法来实现此模式的匹配? 我想做的是:我想匹配BLA,然后向前进行前瞻,直到使用LOOK进行正向前进或使用BLA进行负向前进。但是我不知道将其放入正则表达式中的方法。 作为引擎,我在python中使用r

  • 我在SQL Server2012中创建了以下存储过程... 它将显示类似于下面的输出... 我想让它做的是显示前几周的票数(今天和前6天),即使其中一些天没有门票进入。对他们来说只会显示0。因此,我的输出将看起来包含周四、周五、周六、周日、周一、周二、周三。

  • 问题内容: 是否有任何Django函数可以让我从数据库中获取对象,如果没有匹配项,则为None? 现在我正在使用类似: 但这还不是很清楚,到处都是混乱的。 问题答案: 在Django 1.6中,你可以使用Queryset方法。它返回查询集匹配的第一个对象,如果没有匹配的对象,则返回None。 用法: