Search code examples
sqlpostgresqljoingreatest-n-per-groupsql-limit

Limit join to one row


I have the following query:

SELECT sum((select count(*) as itemCount) * "SalesOrderItems"."price") as amount, 'rma' as     
    "creditType", "Clients"."company" as "client", "Clients".id as "ClientId", "Rmas".* 
FROM "Rmas" JOIN "EsnsRmas" on("EsnsRmas"."RmaId" = "Rmas"."id") 
    JOIN "Esns" on ("Esns".id = "EsnsRmas"."EsnId") 
    JOIN "EsnsSalesOrderItems" on("EsnsSalesOrderItems"."EsnId" = "Esns"."id" ) 
    JOIN "SalesOrderItems" on("SalesOrderItems"."id" = "EsnsSalesOrderItems"."SalesOrderItemId") 
    JOIN "Clients" on("Clients"."id" = "Rmas"."ClientId" )
WHERE "Rmas"."credited"=false AND "Rmas"."verifyStatus" IS NOT null 
GROUP BY "Clients".id, "Rmas".id;

The problem is that the table "EsnsSalesOrderItems" can have the same EsnId in different entries. I want to restrict the query to only pull the last entry in "EsnsSalesOrderItems" that has the same "EsnId".

By "last" entry I mean the following:

The one that appears last in the table "EsnsSalesOrderItems". So for example if "EsnsSalesOrderItems" has two entries with "EsnId" = 6 and "createdAt" = '2012-06-19' and '2012-07-19' respectively it should only give me the entry from '2012-07-19'.


Solution

  • SELECT (count(*) * sum(s."price")) AS amount
         , 'rma'       AS "creditType"
         , c."company" AS "client"
         , c.id        AS "ClientId"
         , r.* 
    FROM   "Rmas"            r
    JOIN   "EsnsRmas"        er ON er."RmaId" = r."id"
    JOIN   "Esns"            e  ON e.id = er."EsnId"
    JOIN  (
       SELECT DISTINCT ON ("EsnId") *
       FROM   "EsnsSalesOrderItems"
       ORDER  BY "EsnId", "createdAt" DESC
       )                     es ON es."EsnId" = e."id"
    JOIN   "SalesOrderItems" s  ON s."id" = es."SalesOrderItemId"
    JOIN   "Clients"         c  ON c."id" = r."ClientId"
    WHERE  r."credited" = FALSE
    AND    r."verifyStatus" IS NOT NULL 
    GROUP  BY c.id, r.id;
    

    Your query in the question has an illegal aggregate over another aggregate:

    sum((select count(*) as itemCount) * "SalesOrderItems"."price") as amount
    

    Simplified and converted to legal syntax:

    (count(*) * sum(s."price")) AS amount
    

    But do you really want to multiply with the count per group?

    I retrieve the the single row per group in "EsnsSalesOrderItems" with DISTINCT ON. Detailed explanation:

    I also added table aliases and formatting to make the query easier to parse for human eyes. If you could avoid camel case you could get rid of all the double quotes clouding the view.