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 Réponses :
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)
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.
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
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 .
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
);
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'
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àOPORlorsque vous le transformez en jointure interne implicite dans votreWHERE? 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/...