Pregunta

Tengo la siguiente consulta:

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;

El problema es que la mesa "EsnsSalesOrderItems" puede tener lo mismo EsnId en diferentes entradas.Quiero restringir la consulta para que solo obtenga la última entrada "EsnsSalesOrderItems" que tiene lo mismo "EsnId".

Por "última" entrada me refiero a lo siguiente:

El que aparece último en la tabla. "EsnsSalesOrderItems".Así por ejemplo si "EsnsSalesOrderItems" tiene dos entradas con "EsnId" = 6 y "createdAt" = '2012-06-19' y '2012-07-19' respectivamente solo debería darme la entrada de '2012-07-19'.

¿Fue útil?

Solución

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;

Su consulta en la pregunta tiene un agregado ilegal sobre otro agregado:

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

Simplificado y convertido a sintaxis legal:

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

¿Pero realmente quieres multiplicar la cuenta por grupo?

Recupero la fila única por grupo en "EsnsSalesOrderItems" con DISTINCT ON.Explicación detallada:

También agregué alias de tablas y formato para que la consulta sea más fácil de analizar para los ojos humanos.Si tu pudieras Evite el caso del camello, podría deshacerse de todas las comillas dobles. nublando la vista.

Otros consejos

Algo como:

join (
  select "EsnId", 
         row_number() over (partition by "EsnId" order by "createdAt" desc) as rn
  from "EsnsSalesOrderItems"
) t ON t."EsnId" = "Esns"."id" and rn = 1

esto seleccionará la última "EsnId" de "EsnsSalesOrderItems" basado en la columna creation_date.Como no publicaste la estructura de tus tablas, tuve que "inventar" un nombre de columna.Puede utilizar cualquier columna que le permita definir un orden en las filas que más le convenga.

Pero recuerda que el concepto de "última fila" sólo es válido si especificas un orden o las filas.Una tabla como tal no está ordenada, ni tampoco es resultado de una consulta a menos que usted especifica un order by

Nigromancia porque las respuestas están desactualizadas.
Aprovecha el LATERAL palabra clave introducida en Pág. 9.3

Izquierda | Derecha | unir internamente LATERAL

Te lo explico con un ejemplo:
Suponiendo que tiene una tabla "Contactos".
Ahora los contactos tienen unidades organizativas.
Pueden tener una unidad organizativa en un momento dado, pero NUNCA en N momentos en el tiempo.

Ahora, si tienes que consultar contactos y OU en un periodo de tiempo (no es una fecha de informe, sino un rango de fechas), podría aumentar N veces el recuento de registros si simplemente se uniera a la izquierda.
Entonces, para mostrar la unidad organizativa, solo necesita unir la primera unidad organizativa para cada contacto (donde lo que será primero es un criterio arbitrario; cuando se toma el último valor, por ejemplo, esa es solo otra forma de decir el primer valor cuando se ordena). por orden de fecha descendente).

En el servidor SQL, usaría la aplicación cruzada (o más bien la APLICACIÓN EXTERNA, ya que necesitamos una unión izquierda), que invocará una función con valores de tabla en cada fila que tiene que unirse.

SELECT * FROM T_Contacts 

--LEFT JOIN T_MAP_Contacts_Ref_OrganisationalUnit ON MAP_CTCOU_CT_UID = T_Contacts.CT_UID AND MAP_CTCOU_SoftDeleteStatus = 1 
--WHERE T_MAP_Contacts_Ref_OrganisationalUnit.MAP_CTCOU_UID IS NULL -- 989

-- CROSS APPLY -- = INNER JOIN 
OUTER APPLY    -- = LEFT JOIN 
(
    SELECT TOP 1 
         --MAP_CTCOU_UID    
         MAP_CTCOU_CT_UID   
        ,MAP_CTCOU_COU_UID  
        ,MAP_CTCOU_DateFrom 
        ,MAP_CTCOU_DateTo   
   FROM T_MAP_Contacts_Ref_OrganisationalUnit 
   WHERE MAP_CTCOU_SoftDeleteStatus = 1 
   AND MAP_CTCOU_CT_UID = T_Contacts.CT_UID 

    /*  
    AND 
    ( 
        (@in_DateFrom <= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateTo) 
        AND 
        (@in_DateTo >= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateFrom) 
    ) 
    */
   ORDER BY MAP_CTCOU_DateFrom 
) AS FirstOE 

En PostgreSQL, a partir de la versión 9.3, tú también puedes hacer eso, solo usa el LATERAL palabra clave para lograr lo mismo:

SELECT * FROM T_Contacts 

--LEFT JOIN T_MAP_Contacts_Ref_OrganisationalUnit ON MAP_CTCOU_CT_UID = T_Contacts.CT_UID AND MAP_CTCOU_SoftDeleteStatus = 1 
--WHERE T_MAP_Contacts_Ref_OrganisationalUnit.MAP_CTCOU_UID IS NULL -- 989


LEFT JOIN LATERAL 
(
    SELECT 
         --MAP_CTCOU_UID    
         MAP_CTCOU_CT_UID   
        ,MAP_CTCOU_COU_UID  
        ,MAP_CTCOU_DateFrom 
        ,MAP_CTCOU_DateTo   
   FROM T_MAP_Contacts_Ref_OrganisationalUnit 
   WHERE MAP_CTCOU_SoftDeleteStatus = 1 
   AND MAP_CTCOU_CT_UID = T_Contacts.CT_UID 

    /*  
    AND 
    ( 
        (__in_DateFrom <= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateTo) 
        AND 
        (__in_DateTo >= T_MAP_Contacts_Ref_OrganisationalUnit.MAP_KTKOE_DateFrom) 
    ) 
    */
   ORDER BY MAP_CTCOU_DateFrom 
   LIMIT 1 
) AS FirstOE 

Intente utilizar una subconsulta en su cláusula ON.Un ejemplo abstracto:

SELECT 
    *
FROM table1
JOIN table2 ON table2.id = (
    SELECT id FROM table2 WHERE table2.table1_id = table1.id LIMIT 1
)
WHERE 
    ...
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top