1
votes

Comment éliminer une ligne qui a l'ID maximum dans la requête SQL?

J'ai besoin d'éliminer la dernière ligne qui a l'ID maximum d'une requête SQL. J'essaie de suivre la requête, mais cela n'a pas généré d'enregistrements

SELECT a.DocEntry, a.Project, a.DocTotal, a.U_Installement
FROM OPCH AS a
LEFT JOIN PCH1 AS b
    ON b.DocEntry = a.DocEntry
LEFT JOIN OPOR AS c
    ON c.DocEntry = b.BaseEntry
    AND a.Project = c.Project
WHERE a.CANCELED = 'N'
AND a.Project = c.Project
GROUP BY a.DocEntry, a.Project, a.DocTotal, a.U_Installement
HAVING MAX(a.DocEntry) <> a.DocEntry;


4 commentaires

dans quelle table vous avez réellement cet identifiant, je veux dire le nom de votre table et le nom de la colonne


Des exemples de données et les résultats souhaités seraient grandement utiles ici.


Pourquoi avez-vous un LEFT JOIN à OPOR lorsque vous le transformez en jointure interne implicite dans votre WHERE ? Mauvaises habitudes à prendre: utiliser des alias de table comme (a, b, c) ou (t1, t2, t3) .


L'argument est également dans cet article stackoverflow.com/questions/2854257/...


4 Réponses :


2
votes

On dirait que cela fonctionnerait:

SELECT a.DocEntry, a.Project, a.DocTotal, a.U_Installement
FROM OPCH AS a
  JOIN PCH1 AS b
    ON b.DocEntry = a.DocEntry
  JOIN OPOR AS c
    ON c.DocEntry = b.BaseEntry
    AND a.Project = c.Project
WHERE a.CANCELED = 'N'
    AND a.DocEntry NOT IN (SELECT MAX(DocEntry) FROM OPCH)


3 commentaires

Autant déplacer a.Project = c.Project dans le ON et changer les 2 jointures en INNER JOIN aussi; laisser JOIN à OPOR en tant que LEFT JOIN et ne pas le changer en INNER JOIN changera le comportement des requêtes lorsque vous déplacez la clause vers ON .


@Larnu, merci, c'est vrai, j'ai corrigé ma réponse


@Renat. . . Cela ne fonctionnera pas , car l’entrée maximale pourrait être filtrée par d’autres conditions.



2
votes

il me semble que vous voulez éliminer chaque id max de groupe et j'ai donc utilisé row_number ()

    with cte as
    (

    SELECT a.DocEntry, a.Project, a.DocTotal, a.U_Installement,
     row_number()over(partitioned by a.Project, a.DocTotal, a.U_Installement
      ordere by a.DocEntry desc) rn
    FROM OPCH AS a
    JOIN PCH1 AS b
        ON b.DocEntry = a.DocEntry
     JOIN OPOR AS c
        ON c.DocEntry = b.BaseEntry
        AND a.Project = c.Project
    WHERE a.CANCELED = 'N'

 ) select * from cte where rn<>1


1 commentaires

La jointure à PCH1 dans un INNER JOIN implicite également, en raison de la clause c.DocEntry = b.BaseEntry dans le ON < / code> de OPOR . Il doit y avoir une ligne à partir de OPOR selon la logique de la requête de l'OP, alors autant en faire tous les deux un INNER JOIN .



0
votes

Tout d'abord, apprenez à utiliser des alias de table significatifs plutôt que des lettres arbitraires. Cela rend les requêtes beaucoup plus faciles à lire.

Deuxièmement, votre clause WHERE transforme les jointures externes en jointures internes.

Ensuite, vous supprimez les doublons - mais ce sont probablement généré par les JOIN . Cela peut être résolu en utilisant EXISTS.

Donc pour votre requête complète:

SELECT DocEntry, Project, DocTotal, U_Installement
FROM (SELECT o.DocEntry, o.Project, o.DocTotal, o.U_Installement,
             MAX(o.DocEntry) OVER () as max_DocEntry
      FROM OPCH o
      WHERE o.CANCELED = 'N' AND
            EXISTS (SELECT 1
                    FROM PCH1 p JOIN
                         OPOR op
                         ON op.DocEntry = p.BaseEntry
                    WHERE p.DocEntry = o.DocEntry AND
                          op.Project = o.Project
                   )
     ) o
WHERE docEntry < max_docEntry;

Ensuite, vous pouvez incorporer des fonctions de fenêtre dans ceci:

SELECT o.DocEntry, o.Project, o.DocTotal, o.U_Installement
FROM OPCH o
WHERE o.CANCELED = 'N' AND
      EXISTS (SELECT 1
              FROM PCH1 p JOIN
                   OPOR op
                   ON op.DocEntry = p.BaseEntry
              WHERE p.DocEntry = o.DocEntry AND
                    op.Project = o.Project
             );


0 commentaires

0
votes

Nous utilisons cette méthode régulièrement:

select a.* from ( 
    SELECT a.DocEntry, a.Project, a.DocTotal, a.U_Installement
    FROM OPCH a 
    GROUP BY a.DocEntry, a.Project, a.DocTotal, a.U_Installement
    HAVING MAX(a.DocEntry) <> a.DocEntry 
) AS a 
LEFT JOIN PCH1 AS b
    ON b.DocEntry = a.DocEntry
LEFT JOIN OPOR AS c
    ON c.DocEntry = b.BaseEntry
    AND a.Project = c.Project
WHERE a.CANCELED = 'N'


0 commentaires