如何强制 PostgreSQL 中 WHERE 子句的顺序?

Sła*_*art 5 postgresql order-by

我在 Postgres 表中有 6 列:

A1 character varying(5)[]
A2 character varying(5)[]
A3 int REFERENCES ... -- FK 
B1 character varying(5)[]
B2 character varying(5)[]
B3 int REFERENCES ... -- FK 
Run Code Online (Sandbox Code Playgroud)

我需要一个SELECT匹配的第一行是获胜者(限制为 1)并匹配 A 组和 B 组。

我知道 Postgres 不关心WHERE子句的顺序,我必须准备一个ORDER子句或找到不同的方法。

我想准备匹配优先级的查找,我的WHERE子句重要性如下:

highest priority: (A1 and B1) OR
.                 (A1 and B2 OR A2 and B1) OR
.                 (A1 and B3 OR A3 and B1) OR
.                 (A2 and B3 OR A3 and B2) OR
lowest priority:  (A3 and B3)
Run Code Online (Sandbox Code Playgroud)

查询匹配 6 个值,例如:
a1 到 A1、a2 到 A2、a3 到 A3、b1 到 B1、b2 到 B2、b3 到 B3

所以A1 和 B1表示a1 与 A1 匹配,b1 与 B1 匹配

在 SQL 这部分写成:

("A1" @> ARRAY['19956']::varchar(5)[] AND "B1" @> ARRAY['27407']::varchar(5)[])

a1='19956', b1='27407'。

尽管 SQL 具有声明性方面,但是否可以将其准备为单个查询?我正在考虑在同一张桌子上进行 5 个连接,但也许有更简单的方法。

Erw*_*ter 6

此信息至关重要:

匹配的第一行是获胜者(限制为 1)

对于单个结果,您实际上不需要任何排序顺序。ORDER BY只是如何解决任务的一个想法。我建议采用完全不同的方法,可能(快得多):

SELECT * FROM tbl WHERE A1 AND B1
UNION ALL
SELECT * FROM tbl WHERE A1 AND B2 OR A2 and B1
UNION ALL
SELECT * FROM tbl WHERE A1 AND B3 OR A3 and B1
UNION ALL
SELECT * FROM tbl WHERE A2 AND B3 OR A3 and B2
UNION ALL
SELECT * FROM tbl WHERE A3 AND B3
LIMIT 1;
Run Code Online (Sandbox Code Playgroud)

这是假设每个SELECT只能返回一行。否则你会得到一个任意的选择,或者你需要添加ORDER BY到括号中的单个 SELECT 以获得确定性的选择。(请参阅下面的链接答案。)

它的美妙之处在于:一旦找到第一行,Postgres 就会停止评估。测试EXPLAIN ANALYZE以查看尾随 SELECT 的“从未执行过”。因此您可以使用索引,这可能意味着性能的数量级。

如果没有匹配项,您可以方便地返回默认行。SELECT之前再追加一个LIMIT 1

顺便说一句,这一个单一的查询。

有关的: