J'ai 2 tables, personne (email, prénom, nom, code postal, nom de lieu)
et localisation (code postal, nom de lieu)
. J'essaie de trouver des gens qui vivent dans des endroits où une seule personne vit. J'ai essayé d'utiliser SELECT COUNT ()
mais j'ai échoué car je ne savais pas quoi compter dans cette situation.
SELECT DISTINCT email, first_name, last_name FROM person INNER JOIN location USING(postcode, place_name) WHERE 1 <= (SELECT COUNT(?))
3 Réponses :
Les fonctions d'agrégation vont toujours avec having
:
SELECT DISTINCT first_value(email) over (partition by place_name), first_value(first_name) over (partition by place_name), first_value(last_name) over (partition by place_name), count(*) FROM person INNER JOIN location USING(postcode, place_name) GROUP BY place_name HAVING count(*) = 1
Pour plus d'informations sur les fonctions de fenêtre (comme first_value
), consultez ce tutoriel .
J'obtiens cette erreur: erreur de syntaxe à ou près de "(" LINE 4: count (*). Pourriez-vous également expliquer la fonction de "first_value" et OVER.
@arthionne désolé, j'ai oublié le point;> first_value
est couramment utilisé avec les fonctions de fenêtre: postgresqltutorial.com/postgresql-first_value-function
Pourriez-vous modifier votre réponse, afin que je puisse l'accepter comme réponse. Et merci pour l'explication.
@arthionne a ajouté, envisagez de voter si cela était utile
Je viens de réaliser qu'il y a des endroits avec le même nom mais des codes postaux différents, par exemple 20814 Bethesda et 20815 Bethesda. Dois-je changer quoi que ce soit pour définir un lieu comme la combinaison du nom et du code postal?
Simplement à la place de place_name
après partition par
et group by
mettre place_name, code postal
J'obtiens cette erreur: la colonne "person.email" doit apparaître dans la clause GROUP BY ou être utilisée dans une fonction d'agrégation
Grâce à l'aide des personnes présentes ici, j'ai trouvé cette réponse:
SELECT first_name, last_name, email FROM person WHERE postcode IN (SELECT postcode FROM person GROUP BY postcode, place_name HAVING COUNT(place_name)=1 ORDER BY postcode) AND place_name IN (SELECT place_name FROM person GROUP BY postcode, place_name HAVING COUNT(postcode)=1 ORDER BY place_name)
Je ferais ceci comme suit. Je trouve cela clair et simple.
select p1.* from person p1 join ( select p.postcode, p.place_name, count(*) cnt from person p group by p.postcode, p.place_name ) t on p1.postcode = t.postcode and p1.place_name = t.place_name and t.cnt = 1
Comment ça marche?
Dans la requête interne (aliasée t
), nous comptons simplement le nombre de personnes vivant dans chaque emplacement.
Ensuite, nous joignons le résultat de celui-ci ( t
) avec la table person
(aliasé p1
) et dans la jointure nous demandons t. cnt = 1
. C'est probablement la manière la plus naturelle de le faire, je pense.
Il ne semble pas y avoir de raison de se joindre à «emplacement», car il n'apporte aucune information qui ne soit pas déjà en «personne».