mysql base de données mondiale: sélectionner le pays avec max de la population
Je veux choisir le pays avec la population la plus élevée. C'est ma requête:
SELECT continent, name, population FROM country HAVING population = MAX(population);
En quelque sorte, elle renvoie 0 lignes.
Si j'utilise une requête imbriquée cela fonctionne:
SELECT continent, name, population FROM country WHERE population = (SELECT MAX(population) FROM country);
Donc ma question est: Quel est le problème avec la première requête?
PS: Vous pouvez télécharger la base de données ici:
http://dev.mysql.com/doc/index-other.html
Bien je pense que j'ai enfin compris l'ensemble du processus. Voici comment cela fonctionne et pourquoi les autres suggestions/solutions ne marche pas:
(Tout d'abord, comme "Dan Bracuk", a déclaré, dans sa réponse, nous devons combiner GROUPE PAR avec AVOIR et ajouter la fonction d'agrégation à la begininng dans l'instruction SELECT)
Donc, nous allons y aller étape par étape et essayez ce qui suit:
SELECT continent, name, population, MAX(population) FROM country;
Cela donne-nous la première ligne annexé MAX(pop) à la fin:
"Amérique Du Nord", "Aruba", "103000", "1277558000"
Donc MAX(de la population) n'est qu'une seule entrée, de sorte qu'il limite le nombre de ligne de 1 et parce que j'ai ajouté le continent, le nom, la population des colonnes, mysql juste sélectionne la première ligne de la table.
Donc, si je écrire:
SELECT continent, name, population, MAX(population) FROM country HAVING population = MAX(population);
- Je obtenir 0 lignes, car 103000 n'est pas égal à 1277558000.
Si j'utilise:
SELECT continent, name, population, MAX(population) FROM country GROUP BY name;
par exemple, j'obtiens la liste de tous les pays, où sur chaque ligne MAX(population) = population.
Si en outre l'ajout d'AVOIR "population = MAX(de la population)" n'a aucun effet puisque c'est déjà le cas.
J'espère que j'ai bien compris et préciser les autres, qui se demandait pourquoi les autres solutions n'ont pas fonctionné.
HAVING without GROUP BY
problème? Si oui, alors c'est une question d'évaluation.Hmmm, je pense que vous avez raison. Mais que voulez-vous dire avec un enjeu de l'évaluation?
J'ai peut-être tort sur l'explication de votre requête échoue, mais je peux faire la lumière sur le "ne pas avoir
GROUP BY
" de l'émission. HAVING
est évalué avant SELECT
et après GROUP BY
. Imaginez que vos résultats se filtrée lentement. FROM
agit tout d'abord, la jointure de tables si nécessaire. Ensuite, WHERE
filtre les résultats de la table. Voici la partie qui vous intéresse: GROUP BY
va transformer ces lignes en groupes, puis HAVING
va supprimer tous les groupes qui ne sont pas qualifiés selon votre condition. SELECT
va maintenant venir travailler sur le reste de la liste. Cela signifie HAVING
ne peut pas fonctionner sur votre SELECT
.Les questions ci-dessus parce que vous êtes en train de faire deux choses: votre référencement sur
population
quand il ne peut pas être référencée encore. Plus, vous n'avez pas de GROUP BY
de "forcer" population
à apparaître. Je ne suis pas expert en SQL donc la question avec votre requête peut être hors de la marque. Cependant, la logique de l'évaluation semble à l'appui de cette.J'ai édité ma réponse, et pense que cela répond à votre question complètement.
OriginalL'auteur A.B. | 2013-12-02
Vous devez vous connecter pour publier un commentaire.
Wow, après beaucoup d'essais et d'erreurs, je vois que le problème est aujourd'hui. Tout d'abord, votre requête initiale semble erroné. Avec la table de base de données que vous utilisez, vous pouvez avoir plusieurs régions à l'intérieur du continent. Par conséquent, votre requête ne retournera (si il fonctionne correctement) le continent avec la plus importante de la région au lieu d'une somme de toutes les régions. Deuxièmement, vous ne pouvez absolument utiliser le
max
fonction au sein de l'having
clause, comme dans cet exemple:(Si vous n'avez pas de groupe par Continent, vous ne recevrez qu'une seule rangée de secours.)
Cependant, ce n'est vraiment d'aucune utilité pour vous, car à ce stade, le max de la population est ce que la population est pour cette ligne. Pas pour chaque ligne. C'est parce que le
having
clause est seulement en regardant les valeurs pour qu'une ligne (pour toutefois, le nombre de lignes que vous avez). N'importe quoi, vous aurez besoin d'une sous-requête si vous souhaitez utiliser lehaving
clause dans votre cas (ou vous pouvez utiliser ma requête initiale), comme ci-dessous.http://sqlfiddle.com/#!2/3ab95/26
(Ce sqlfiddle ne contient pas toutes les lignes de la table, de sorte que le résultat peut être différent de votre propre.)ok, j'ai essayé juste pour des fins de test: "SÉLECTIONNEZ continent, le nom, la population DE pays AYANT de MAX(population) > 1;" et il me renvoie qu'une seule ligne (la première) althopugh il devrait revenir, presque toutes les lignes. Pourquoi?
Avec AVOIR, il renvoie 0 lignes. Par OÙ l'erreur de syntaxe. Donc il ne marche pas. Mais je me demande aussi pourquoi votre suggestion ne fonctionne pas.
Par la façon dont vous pouvez télécharger la base de données ici: dev.mysql.com/doc/index-other.html
La première requête que vous avez suggéré était une bonne requête pour obtenir la réponse exacte.
OriginalL'auteur James
Il ya un couple de choses de mal avec elle. En fait, dans certains moteurs de base de données, il serait jeter une erreur.
Tout d'abord, le devoir mot-clé est utilisé avec l'ensemble des résultats, pas sur des champs. Ici est un exemple.
Noter que certaines bases de données ne vous permettra pas d'utiliser les noms d'alias dans la clause having.
Ensuite, vous dites ceci:
max(de la population) n'a pas vraiment été définis. Vous n'êtes pas le sélectionnant à partir de n'importe où.
Dans l'exemple dans le lien,
aggregate_function(column_name)
est définie dans leselect
clause. C'est pourquoi ils peuvent l'utiliser à l'intérieur de lahaving
clause.eh bien, pourquoi dow-ce pas le travail que? "SÉLECTIONNEZ continent, nom, population, MAX(population) DE pays AYANT la population = MAX(de la population);"
Je ne suis pas sûr. C'est ce que je me demande moi-même. :/ C'est quelque chose que je vais vérifier quand j'arrive au travail demain. lol~
OriginalL'auteur Dan Bracuk
Même si j'ai déjà posté ma réponse dans les commentaires, je me sens obligé de le signaler. Rappelez-vous, ce pourrait même ne pas être correct, mais pour Q&A, je doit à tout le moins, tenter de souligner quel est le problème avec la première requête.
Premier point: Il n'est pas entièrement mal. Il arrive juste à être "non-conformiste". Il y a des cas où les gens ont forcé les requêtes semblables à travailler, mais c'est presque toujours une action qui ne demande qu'une longue explication. Il suffit de dire, "hack-gratuit",
HAVING
fonctionne (presque) uniquement avecGROUP BY
.Deuxième est l'évaluation des flux de SQL. Je suis peut-être hors de la marque ici, et depuis je n'ai pas eu d'expérience avec SQL depuis un certain temps, mais l'ordre, je pense, devrait rester le même.
FROM-WHERE-GROUP BY-HAVING-SELECT-ORDER BY
a été l'une des premières choses que j'ai appris sur elle, et il agit comme un filtre de toutes sortes. Va pour unHAVING MAX(population)
lorsqu'il n'est pas sorti de la population est encore un peu de peine à exécuter. C'est la partie où les sous-requêtes existent: ainsi, vous pouvez identifier une "cible" de la valeur qui peut être référencé avantSELECT
jamais vient autour.Nous allons étape par le biais de votre deuxième ligne, l'un avec une sous-requête:
FROM country
obtient tous les pays. Puis vous avez dit à SQL sur laWHERE
partie, "Hey, nous allons définir un filtre. Mais le filtre a besoin d'une autre requête. Donc, nous allons le faire." Elle renvoie une valeur, qui est laMAX(population
de la table. Maintenant, il retourne cette valeur àWHERE
doncWHERE
filtre toutes les lignes avec une population qui ne correspond pas à l'état. Ensuite, il retourne sur le continent, le nom et la population du pays. Assez Simple.Maintenant, la seconde: Encore une fois,
FROM country
obtient tous les pays. Vous n'avez pas deWHERE
vous travaillez donc avec la table de base. Vous n'avez pas mis dans unGROUP BY
soit, pas de regroupement qui s'est passé. Mais alors vous avez jeté dans unHAVING
SQL s'arrête et demande à, "Où sont les groupes de qualification je devrais jeter? Mais même si il n'y a pas de groupes et par chance, cette requête est un peu valable, où est mon condition?" Si vous avez fourni une condition, mais cette condition repose sur le simple fait Qui estMAX(population)
référence? Vous n'avez pas choisi de le sortir de la liste, de toute façon, depuisSELECT
encore arriver.En essence, c'est en partie la raison pour laquelle vous ne pouvez pas faire un
SELECT name FROM country WHERE population = MAX(population)
. Aussi loin que le flux va, il ne sait pas le max de la population, car il doit encore être évalué. C'est comme demander à un apple sélecteur pour sélectionner la meilleure des pommes d'un verger quand il n'a pas vu toutes les pommes encore.OriginalL'auteur Jerome Montino
Tandis que le
WHERE
clause est appliquée à la table source, leHAVING
clause est appliquée à les données agrégées comme une dernière étape avant de retourner le résultat.Dans le cas de MySQL, c'est ce qui se passe avec votre requête:
MAX
, MySQL conclut que la requête doit être une agrégationGROUP BY
clause, l'agrégation est sur la table de retourner une seule lignecontinent
,name
, etpopulation
qui ne sont pas dans leGROUP BY
sans une fonction d'agrégation, tandis que d'autres bases de données SQL serait jeter une erreur, MySQL fait juste retourne les valeurs d'une durée indéterminée ligneHAVING
clause vérifie si la ligne retournée a la population maximaleHabituellement, cela doit retourner 0 lignes, mais selon la configuration de la table, vous pouvez réellement obtenir une réponse correcte comme vous pouvez le voir dans cette sql violon: http://sqlfiddle.com/#!2/79835/7, mais c'est trompeur, et se décompose pour le minimum.
Si vous utilisez un
GROUP BY
clause ou d'une fonction d'agrégation commeMAX
,COUNT
, ouSUM
votre requête est une agrégation. Dans ce cas, tous les champs que vous utilisez doivent généralement être inclus dans lesGROUP BY
ou enfermé dans une fonction d'agrégation. Ne pas le faire peut conduire à des bogues subtils qui sont difficiles à dépister.Voir aussi: GROUPE PAR le comportement lorsque aucune des fonctions d'agrégation sont présents dans la clause SELECT
OriginalL'auteur unique2