2010-01-28 3 views
3

Problème: J'ai une liste de noms et d'adresses. Certains noms (personnes) ont la même adresse (rue, code postal, ville) que d'autres. Je veux sélectionner tous ces noms avec des adresses avec pas plus de trois occurrences et du reste les trois premiers noms chacun d'un groupe pointant vers la même adresse. Exemple: Comment limiter un ensemble de résultats SQL à des éléments pas trop communs

 
Albert | Adr1 
Berta | Adr1 
Cesar | Adr1 
Donald | Adr1 
Eric | Adr2 
Fritz | Adr2 
Gerd | Adr2 
Henry | Adr3

Le jeu de résultats doit être

Albert | Adr1 
Berta | Adr1 
Cesar | Adr1 
Eric | Adr2 
Fritz | Adr2 
Gerd | Adr2 
Henry | Adr3

Donald manque parce qu'il est le 4ème d'un groupe avec la même adresse. Ce résultat peut-il être obtenu avec des UNIONs et des sous-requêtes? Quelque chose comme

select * from addresses where address in 
(select address from addresses group by address having count(address) <= 3) 
UNION 
select * from addresses where address in 
(select address from addresses group by address having count(address) > 3 limit 3)

Je sais que cette requête est erronée, car elle limite le jeu de résultats complet d'adresses avec plus de 3 occurences. Je me demande si cela peut être fait dans un seul SELECT avec UNIONs et sous-requêtes. Je vais le faire maintenant de façon procédurale avec PHP/MySQL, mais juste pour le plaisir serait intéressé par une solution SQL seule.

J'ai jeté un oeil à SQL query with limit on rows from one table, not the result set, mais cela ne reflète pas ma situation - ou est-ce le cas?

+0

comment pouvez-vous reconnaître que Donald est le quatrième membre du groupe? comment ces données sont triées? – Beatles1692

+0

Est-ce MySQL ou Sql Server? –

+0

L'ordre de tri n'a pas d'importance. Il doit y avoir 3 adresses sur plus de 3. Le serveur est MySQL 5.1 –

Répondre

1

Vous pouvez essayer quelque chose comme

SELECT PersonName, 
     Address 
FROM (
      SELECT *, 
        (SELECT COUNT(1) FROM addresses WHERE Address = a.Address AND PersonName < a.PersonName) CountLess 
      FROM addresses a 
     ) sub 
WHERE sub.CountLess <= 2 
+0

Très ingénieux. Merci beaucoup. –

3
select name, address 
from 
(select *, row_number() over (partition by address order by name) as namenum 
    from yourTable 
) t 
where namenum <= 3; 
+1

Est-ce la norme SQL? –

+0

Cela fonctionne dans SQL Server et Oracle et DB2 prennent tous deux en charge la clause OVER. Je ne pense pas que mysql ait encore compris cette partie de la norme, tout comme SQL Server ne nécessite pas encore de point-virgule. –

+0

Ceci n'est pas supporté par MySQL. La solution m'a indiqué à http://explainextended.com/2009/09/14/mysql-emulating-row_number-with-multiple-order-by-conditions/, cependant, où un problème similaire est traité et la fonctionnalité de la solution Robs est émulé. –

Questions connexes