1
votes

Comment trouver des colonnes qui n'ont qu'une seule valeur - PostgreSQL

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(?))


1 commentaires

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».


3 Réponses :


1
votes

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 .


7 commentaires

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



0
votes

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)


0 commentaires

1
votes

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.


0 commentaires