如何按照数组元素的顺序对查询结果进行排序?
How to order query result according to the order of array elements?
我在 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[]
)
)
它returns:
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[]
)
我该怎么做?
ORDER BY idx(your_array, your_element)
或
ORDER BY your_array # your_element
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
基础知识:
- 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,您可以在其中提供数组 once. unnest()
它立即WITH ORDINALITY
根据数组元素的顺序得到行号(rn
)。
与其将你的子查询塞进一个数组然后再转换回来,不如直接使用它。便宜得多。排序顺序直接来自 id
。
而不是使用 NOT IN
从给定数组中排除 ID(这对于 NULL 值可能很棘手)使用 LEFT JOIN / IS NULL
:
- Select rows which are not present in other table
只需在这两部分后面加上UNION ALL
。 UNION ALL
查询的每条腿上的括号必须有单独的 ORDER BY
:
- Sum results of a few queries and then find top 5 in SQL
最后SELECT
中的JOIN
到question
现在是多余的,我把它去掉了。
我在 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[]
)
)
它returns:
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[]
)
我该怎么做?
ORDER BY idx(your_array, your_element)
或
ORDER BY your_array # your_element
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
基础知识:
- 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,您可以在其中提供数组 once.
unnest()
它立即WITH ORDINALITY
根据数组元素的顺序得到行号(rn
)。与其将你的子查询塞进一个数组然后再转换回来,不如直接使用它。便宜得多。排序顺序直接来自
id
。而不是使用
NOT IN
从给定数组中排除 ID(这对于 NULL 值可能很棘手)使用LEFT JOIN / IS NULL
:- Select rows which are not present in other table
只需在这两部分后面加上
UNION ALL
。UNION ALL
查询的每条腿上的括号必须有单独的ORDER BY
:- Sum results of a few queries and then find top 5 in SQL
最后
SELECT
中的JOIN
到question
现在是多余的,我把它去掉了。