Set limit to array_agg()

2019-04-24 01:44发布

问题:

I have the following Postgres query:

SELECT array_agg("Esns".id ) 
FROM public."Esns", 
     public."PurchaseOrderItems" 
WHERE 
    "Esns"."PurchaseOrderItemId" = "PurchaseOrderItems".id 
    AND "PurchaseOrderItems"."GradeId"=2 
LIMIT 2;

The limit will affect the rows. I want it to limit the array_agg() to 2 items. The following query works but I get my output with each entry in quotes:

SELECT array_agg ("temp")  
FROM (
    SELECT "Esns".id 
    FROM public."Esns", 
         public."PurchaseOrderItems" 
    WHERE 
        "Esns"."PurchaseOrderItemId" = "PurchaseOrderItems".id 
        AND "PurchaseOrderItems"."GradeId"=2 
    LIMIT 4
) as "temp" ;

This give me the following output

{(13),(14),(15),(12)}

Any ideas?

回答1:

select id[1], id[2]
from (
    SELECT array_agg("Esns".id ) as id
    FROM public."Esns", 
         public."PurchaseOrderItems" 
    WHERE 
        "Esns"."PurchaseOrderItemId" = "PurchaseOrderItems".id 
        AND "PurchaseOrderItems"."GradeId"=2 
) s

or if you want the output as array:

SELECT (array_agg("Esns".id ))[1:2] as id_array
FROM public."Esns", 
     public."PurchaseOrderItems" 
WHERE 
    "Esns"."PurchaseOrderItemId" = "PurchaseOrderItems".id 
    AND "PurchaseOrderItems"."GradeId"=2 


回答2:

The quotes in the result are decorators for the row type. You are not building an array of whole rows (which happen to contain a single column). Use the column instead.

Also, direct array construction from a query result is typically simpler and faster:

SELECT ARRAY (
   SELECT e.id 
   FROM   public."Esns" e
   JOIN   public."PurchaseOrderItems" p ON p.id = e."PurchaseOrderItemId"
   WHERE  p."GradeId" = 2 
   --  ORDER BY ???
   LIMIT  4  -- or 2?
   )

You need to ORDER BY something if you want a stable result and / or pick certain rows. Otherwise the result is arbitrary and can change at any time.

While being at it I rewrote the query with explicit JOIN syntax, which is generally preferable, and used aliases to simplify.