如何根据数组元素的顺序对查询结果进行排序?
Posted
技术标签:
【中文标题】如何根据数组元素的顺序对查询结果进行排序?【英文标题】:How to order query result according to the order of array elements? 【发布时间】:2015-04-11 04:42:21 【问题描述】:我在 Postgres 9.4 中有这个查询:
select id from question where id = any(
array_cat(
ARRAY[0,579489,579482,579453,561983,561990,562083]::integer[],
(select array(
select id from question where id not in
(0,579489,579482,579453,561983,561990,562083)
and status in (1, -1)
and created_at > 1426131436 order by id desc offset 0 limit 10 )
)::integer[]
)
)
返回:
id
--------
561983
561990
562083
579453
579482
579489
580541
580542
580543
580544
580545
580546
580547
580548
580549
580550
(16 rows)
但它的顺序不正确。我需要根据子数组的结果排序的结果:
array_cat(
ARRAY[0,579489,579482,579453,561983,561990,562083]::integer[],
(select array(
select id from question where id not in
(0,579489,579482,579453,561983,561990,562083)
and status in (1, -1)
and created_at > 1426131436 order by id desc offset 0 limit 10 )
)::integer[]
)
我该怎么做?
【问题讨论】:
你的 Postgres 版本? 【参考方案1】:基础知识:
PostgreSQL unnest() with element number由于您使用的是 Postgres 9.4,因此您可以使用新的 WITH ORDINALITY
:
WITH t AS (
SELECT *
FROM unnest('0,579489,579482,579453,561983,561990,562083'::int[])
WITH ORDINALITY AS t(id, rn)
)
(
SELECT id
FROM question
JOIN t USING (id)
ORDER BY t.rn
)
UNION ALL
(
SELECT id
FROM question
LEFT JOIN t USING (id)
WHERE t.id IS NULL
AND status IN (1, -1)
AND created_at > 1426131436
ORDER BY id DESC
LIMIT 10
);
解释
由于您两次使用相同的数组,我在查询前添加了一个 CTE,您可以在其中提供数组一次。 unnest()
它立即WITH ORDINALITY
根据数组元素的顺序获取行号(rn
)。
不要将子查询填充到数组中并将其转换回来,而是直接使用它。便宜得多。排序顺序直接来源于id
。
使用LEFT JOIN / IS NULL
,而不是使用NOT IN
(这对于NULL 值可能会很棘手)从给定数组中排除ID:
只需将两个部分附加UNION ALL
。在 UNION ALL
查询的每条腿上,括号必须有单独的 ORDER BY
:
最后的SELECT
中的JOIN
到question
现在是多余的,我把它去掉了。
【讨论】:
我不知道,这似乎很完美:) @mathieu:我更进一步。现在应该很快了。 我真的不需要答案,因为我不是问题的作者,但我找到了实现这个有趣的方法...... Postgres 提供了如此多的可能性,很难全部了解:) @ErwinBrandstetter 它工作。我认为它在 9.4 中很完美,非常感谢。 对此进行一些更改:从问题 q 中选择 q.id 加入(从 unnest 中选择*(array_cat(数组[0,579489,579482,579453,561983,561990,562083]::integer[ ], (select array( select id from question where id not in (0,579489,579482,579453,561983,561990,562083) 和状态在 (1, -1) 和 created_at > 1426131436 order by id desc offset 0 limit 10 ) )::integer[] ) ) WITH ORDINALITY as ids(id, rn) ) as tmp on q.id = tmp.id order by tmp.rn【参考方案2】:ORDER BY idx(your_array, your_element)
或
ORDER BY your_array # your_element
intarray
select id from question where id = any(
array_cat(
ARRAY[0,579489,579482,579453,561983,561990,562083]::integer[],
(select array(
select id from question where id not in
(0,579489,579482,579453,561983,561990,562083) and status in (1, -1)
and created_at > 1426131436 order by id desc offset 0 limit 10 )
)::integer[]
)
) ORDER BY array_cat(
ARRAY[0,579489,579482,579453,561983,561990,562083]::integer[],
(select array(
select id from question where id not in
(0,579489,579482,579453,561983,561990,562083) and status in (1, -1)
and created_at > 1426131436 order by id desc offset 0 limit 10 )
)::integer[]
) # id
【讨论】:
以上是关于如何根据数组元素的顺序对查询结果进行排序?的主要内容,如果未能解决你的问题,请参考以下文章