Je suis nouveau dans Oracle et le monde SQL. J'ai un petit problème avec une requête que je n'arrive pas à comprendre pendant toute ma vie. J'ai passé quelques heures à essayer différentes approches et je ne parviens pas à obtenir le résultat escompté. Alors voici ma requête:
SELECT *
from(Select membership.mem_desc,membership.mem_max_rentals,membership_history.mem_type,
count(membership_history.MEM_TYPE) as membership_count
from membership_history
JOIN membership ON membership.mem_type = membership_history.mem_type
group by (membership_history.mem_type,membership.mem_desc,membership.mem_max_rentals)
) g
WHERE g.membership_count = (select MAX(membership_count) from g);
La requête interne fonctionne donc parfaitement et renvoie deux résultats. Maintenant que j'ai ces deux valeurs, j'essaie de comprendre comment retourner la ligne avec la valeur maximale de membership_count, c'est-à-dire où je reste bloqué. Dans la requête ci-dessus, j'ai essayé d'utiliser MAX () dans la clause where mais à l'intérieur de cette sélection, je reçois toujours l'erreur 'table non trouvée' (qui signifie 'g'). Ma question est donc la suivante: comment utiliser la fonction MAX () sur les résultats de ma sous-requête? Toutes les pensées ou suggestions seraient grandement appréciées !!!!!
Vous n'avez pas besoin de la sous-requête qui trouve la valeur maximale.
Au lieu, ; vous avez juste besoin de la première ligne après avoir ordonné les lignes:
select * from (
select
membership.mem_desc,
membership.mem_max_rentals,
membership_history.mem_type,
count(membership_history.MEM_TYPE) as membership_count
from membership_history
JOIN membership ON membership.mem_type = membership_history.mem_type
group by (membership_history.mem_type,membership.mem_desc,membership.mem_max_rentals)
ORDER BY 4 DESC -- Added this line
) g
WHERE ROWNUM = 1. -- Added this line
Ceci est tout bon SQL.
La meilleure façon de rechercher une valeur de colonne à l'aide de la valeur de colonne max primaire est la suivante:
SELECT .... from tablename
WHERE ... AND
(SELECT max(primary key name) FROM tablename WHERE .... ) = primary_key_name
cet exemple renverra une valeur scalaire.
J'ai eu un problème similaire dans une requête Access ... d'après certains commentaires de ce fil de discussion, devons-nous comprendre que la fonction ACCESS MAX ne doit être utilisée que sur/avec les champs de clé primaire? ... fondamentalement, j'ai un tableau qui définit les adresses relatives à une entité, MAIS, avec une légère torsion; 1) une fois sauvegardé, aucun enregistrement ne peut être supprimé ou modifié (ce qui signifie qu'une entité peut avoir plusieurs enregistrements d'adresse), 2) toute adresse d'entité actuelle peut en avoir un; HOME (1 enregistrement) ou HOME et MAIL (2 enregistrements) ... chaque enregistrement d’adresse a un identifiant (ID) (clé primaire numérotée automatiquement), un identifiant HOME (HID) correspondant à l’enregistrement HOME (ID) (l’IDH n’est n'est PAS unique) et un ID d'entité (EID) ... donc ... lorsque j'essaie d'utiliser une sous-requête pour obtenir la valeur max (HID) d'une entité donnée, je veux uniquement que l'adresse actuelle soit renvoyée ... Ce que j’ai trouvé en utilisant MAX dans une sous-requête, c’est que son exécution échoue car ACCESS pense à tort qu’il a trop d’enregistrements correspondants pour la sous-requête ... ou ... il renvoie incorrectement les lignes qu’il ne devrait pas renvoyer.
Le seul moyen que j'ai trouvé pour contourner ce problème était de remplacer la sous-requête max par une fonction Max qui renvoie la valeur MAX HID d'une entité (la fonction utilise l'instruction de sous-requête avec la logique DAO dans VBA)
Voici la sous-requête HOME qui fait partie de la requête principale (la requête principale doit renvoyer une ligne par entité sous la forme: EID, Home.Address, Mail.Address).
Select *
From tbAddresses As tba1
Where tba1.aType = "Home"
And tba1.HID = (Select MAX(tba2.HID)
From tbAddresses As tba2
Where tba1.EID = tba2.EID)
La requête principale ne fonctionne correctement que lorsque les clauses Where Home et Mail (non illustrées) sont remplacées par la fonction ci-dessous. Si la sous-requête MAX est incluse comme ci-dessus, cela ne fonctionne pas.
Donc, si la fonction MAX nécessite l'utilisation d'un champ PRIMARY KEY, cela pourrait expliquer pourquoi mes requêtes échouent, bien que cela puisse sembler être une limitation majeure.
Where tba1.HID = fnGetMaxHID(tba1.EID)
Voici quelques données de test qui ne devraient renvoyer que 3 lignes
ID HID EID aType Address
1 1 100 Home Blah 1
2 2 101 Home Blah 2
3 2 101 Mail PO Box Blah 0
4 4 102 Home Blah 3
5 5 101 Home Blah 4
Une dernière note, plusieurs versions de Access Pro; 2002, 2003 et 2016 ont été testés et produisent tous les mêmes résultats. Donc, ce problème est soit une bizarrerie inhérente à la fonction max, soit une sorte de bogue qui a peut-être été ignoré ou passé inaperçu? ... la fonction fonctionne comme une solution de contournement pour moi mais peut ne pas fonctionner pour les autres. Ce serait donc agréable si la fonction MAX était clarifiée.
Vous pouvez essayer quelque chose comme
SELECT membership.mem_desc,membership.mem_max_rentals,membership_history.mem_type, membership_count, rank() over ORDER BY membership_count DESC as ranky
from
(Select membership.mem_desc,membership.mem_max_rentals,membership_history.mem_type,
count(membership_history.MEM_TYPE) as membership_count
from membership_history
JOIN membership ON membership.mem_type = membership_history.mem_type
group by (membership_history.mem_type,membership.mem_desc,membership.mem_max_rentals)
)
WHERE ranky =1;
Vous ne pouvez pas utiliser une table dérivée directement dans la clause où elle donnera table or view does not exist
erreurso pour obtenir la valeur de comptage maximale, vous pouvez utiliser la clause HAVING
ou Analytical Functions
ou Rownum
comme
select * from
(Select membership.mem_desc,membership.mem_max_rentals,membership_history.mem_type,
count(membership_history.MEM_TYPE) as membership_count
from membership_history a
JOIN membership b ON b.mem_type = a.mem_type
group by (membership_history.mem_type,membership.mem_desc,membership.mem_max_rentals)
having count(a.MEM_TYPE) = (Select
MAX(count(a.MEM_TYPE)) from membership_history a
JOIN membership b ON b.mem_type = a.mem_type
group by (a.mem_type,b.mem_desc,b.mem_max_rentals)));
(OU)
select * from
(SELECT g.*,rank() over (order by membership_count desc) rnk from
(Select membership.mem_desc,membership.mem_max_rentals,membership_history.mem_type,
count(membership_history.MEM_TYPE) as membership_count
from membership_history
JOIN membership ON membership.mem_type = membership_history.mem_type
group by (membership_history.mem_type,membership.mem_desc,membership.mem_max_rentals)) g)
WHERE rnk=1;
(OU)
select * from
(SELECT g.*,rownum rn from
(Select membership.mem_desc,membership.mem_max_rentals,membership_history.mem_type,
count(membership_history.MEM_TYPE) as membership_count
from membership_history
JOIN membership ON membership.mem_type = membership_history.mem_type
group by (membership_history.mem_type,membership.mem_desc,membership.mem_max_rentals)
order by membership_count desc) g)
WHERE rn=1;
Je pense que la solution la plus propre consiste à utiliser la condition de comparaison ALL. Il est utilisé pour comparer une valeur à une liste ou à une sous-requête.
SELECT
m.mem_desc,
m.mem_max_rentals,
mh.mem_type,
COUNT(mh.mem_type) as membership_count
FROM membership_history mh
JOIN membership m ON m.mem_type = mh.mem_type
GROUP BY mh.mem_type,m.mem_desc,m.mem_max_rentals
HAVING membership_count >= ALL (
SELECT count(*)
FROM membership_history
GROUP BY mem_type
)