如何根据数组元素的顺序排序查询结果?

时间:2015-04-11 04:42:21

标签: sql postgresql sql-order-by set-returning-functions unnest

我在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[]
    )

我该怎么做?

2 个答案:

答案 0 :(得分:3)

基础:

由于您使用的是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
);

解释

  1. 由于您使用的是同一个数组两次,因此我使用CTE在查询前面添加 一次 unnest()根据数组元素的顺序立即WITH ORDINALITY获取行号(rn

  2. 不是将子查询填充到数组中并将其转换回来,而是直接使用它。便宜得多。排序顺序直接来自id

  3. 使用NOT IN代替使用LEFT JOIN / IS NULL从给定数组中排除ID(使用NULL值可能会很棘手):

  4. 只需使用UNION ALL附加两个部分即可。括号必须在ORDER BY查询的每一段都有单独的UNION ALL

  5. 最终JOIN中的questionSELECT现在已经多余了,我将其剥离了。

答案 1 :(得分:0)

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