J'ai une table col
où j'ai:
ORA-00920: invalid relational operator
I a renvoyé des données en utilisant une requête par année et par dept_id:
SELECT * FROM offc.col WHERE ( dept_id, year, marks ) IN (SELECT dept_id, year, Max(marks) marks FROM offc.col GROUP BY dept_id, year ORDER BY dept_id, year);
Les données que j'ai obtenues étaient:
Ici, il n'y a pas de problème car mon sql fonctionne correctement. Donc, j'avais besoin d'extraire toutes les informations de la table col
, donc j'ai utilisé la sous-requête comme: p >
SELECT dept_id, year, Max(marks) marks FROM offc.col GROUP BY dept_id, year ORDER BY dept_id, year
Mais, j'ai eu une erreur comme:
select * from offc.col;
J'ai cherché cette erreur sur d'autres pages également, mais je les ai trouvées comme parenthèses mal placées erreur, mais dans mon cas, je ne sais pas ce qui se passe ici?
3 Réponses :
Au lieu d'agréger, vous pouvez filtrer avec une sous-requête corrélée:
select c.* from offc.col c inner join ( select dept_id, year, max(marks) marks from offc.col group by dept_id, year ) m on m.dpt_id = c.dept_id and m.year = c.year and m.marks = m.marks
Un index sur (dept_id, year, marks)
accélérerait cette requête.
/ p>
Une autre option consiste à utiliser la fonction de fenêtre row_number()
:
select * from ( select c.*, row_number() over(partition by dept_id, year order by marks desc) rn from offc.col c ) x where rn = 1 order by dept_id, year
Si vous voulez pour vous en tenir à l'agrégation, vous pouvez alors joindre votre sous-requête avec la table d'origine comme suit:
select c.* from offc.col c where marks = ( select max(marks) from offc.col c1 where c1.dept_id = c.dept_id and c1.year = c.year ) order by dept_id, year
pouvez-vous également m'aider avec la fonction d'agrégation? J'apprends donc j'ai besoin de connaissances de base de base
@KarkiAshwin: la sous-requête corrélée est également une connaissance de base, et elle donne généralement de meilleures performances (et une meilleure lisibilité). Pourtant, j'ai mis à jour ma réponse avec une solution qui utilise l'agrégation.
Je suggérerais d'utiliser la fonction analytique dense_rank
car elle peut renvoyer deux départements s'ils ont les mêmes notes la même année. (votre logique actuelle est la même que celle-ci)
Row_number ne vous donnera qu'un seul enregistrement aléatoire si deux départements ont les mêmes notes la même année.
SELECT * FROM offc.col WHERE ( dept_id, year, marks ) IN (SELECT dept_id, year, Max(marks) marks FROM offc.col GROUP BY dept_id, year -- ORDER BY dept_id, -- year );
De plus, votre requête est correcte, supprimez simplement la commande.
select * from ( select c.*, dense_rank() over(partition by dept_id, year order by marks desc nulls last) as dr from offc.col c ) x where dr = 1 order by dept_id, year
Démo d'erreur avec order by
et fonctionne bien sans order by
.
Cheers !!
Effectuez un INNER JOIN avec votre sous-requête:
SELECT c.* FROM offc.col c INNER JOIN (SELECT dept_id, year, Max(marks) AS MAX_MARK FROM offc.col GROUP BY dept_id, year) s ON s.DEPT_ID = c.DEPT_ID AND s.YEAR = c.YEAR AND s.MAX_MARK = c.MARKS ORDER BY c.DEPT_ID, c.YEAR
Un INNER JOIN ne renvoie que les lignes où la condition de jointure est satisfaite, donc toutes les lignes de OFFC.COL qui n'ont pas la valeur maximale pour MARKS pour un DEPT_ID et un YEAR particuliers ne seront pas renvoyés.
L'opérateur
IN
ne fonctionne pas comme ça. Vous pouvez tester une valeur unique par rapport à une liste ou une sous-requête:DEPT_ID IN (2, 5, 6)
ouDEPT_ID IN (SELECT id FROM ... )
.