SQL: Tri par Email nom de domaine

Quelle est la déclaration SQL la plus courte et/ou efficace pour trier une table avec une colonne d'adresse email par son fragment de nom de domaine?

c'est essentiellement ignorer ce qui est avant "@" dans les adresses e-mail et insensible à la casse. Ignorons les noms de domaine internationalisés pour celui-ci.

cible: mySQL, MSSQL, Oracle

exemples de données de TABLE1

id   name           email 
------------------------------------------
 1   John Doe       johndoe@domain.com
 2   Jane Doe       janedoe@helloworld.com
 3   Ali Baba       ali@babaland.com
 4   Foo Bar        foo@worldof.bar.net
 5   Tarrack Ocama  me@am-no-president.org

Commander Par E-mail

SELECT * FROM TABLE1 ORDER BY EMAIL ASC

id   name           email 
------------------------------------------
 3   Ali Baba       ali@babaland.com
 4   Foo Bar        foo@worldof.bar.net
 2   Jane Doe       janedoe@helloworld.com
 1   John Doe       johndoe@domain.com
 5   Tarrack Ocama  me@am-no-president.org

Ordre Par Domaine

SELECT * FROM TABLE1 ORDER BY ?????? ASC

id   name           email 
------------------------------------------
 5   Tarrack Ocama  me@am-no-president.org
 3   Ali Baba       ali@babaland.com
 1   John Doe       johndoe@domain.com
 2   Jane Doe       janedoe@helloworld.com
 4   Foo Bar        foo@worldof.bar.net

EDIT:

Je ne demande pas une seule déclaration SQL qui fonctionnera sur tous les 3 moteurs SQL ou plus. Toute contribution est bienvenue. :)

17
demandé sur o.k.w 2009-11-28 07:15:54

13 réponses

Essayez ceci

Requête(Sql Serveur):

select * from mytbl
order by SUBSTRING(email,(CHARINDEX('@',email)+1),1)

Query(Oracle):

select * from mytbl
order by substr(email,INSTR(email,'@',1) + 1,1)

Query (for MySQL)

pygorex1 already answered

Sortie:

id Nom courriel

5   Tarrack Ocama   me@am-no-president.org
3   Ali Baba    ali@babaland.com
1   John Doe    johndoe@domain.com
2   Jane Doe    janedoe@helloworld.com
4   Foo Bar foo@worldof.bar.net
19
répondu priyanka.sarkar 2009-11-28 06:52:37

Pour MySQL:

select email, SUBSTRING_INDEX(email,'@',-1) AS domain from user order by domain desc;

pour les cas insensibles:

select user_id, username, email, LOWER(SUBSTRING_INDEX(email,'@',-1)) AS domain from user order by domain desc;
15
répondu leepowers 2009-11-28 04:22:18

si vous voulez que cette solution soit mise à l'échelle, vous devriez essayez d'extraire des sous-colonnes. Les fonctions par rangée sont notoirement lentes car la table devient de plus en plus grande.

droit la chose à faire dans ce cas est de déplacer le coût de l'extraction de select (où cela arrive souvent) à insert/update où il se produit moins (dans la plupart des bases de données normales). En supportant le coût seulement sur insert et update, vous augmentez considérablement l'ensemble de la l'efficacité de la base de données, puisque c'est le point dans le temps où vous devez le faire (c.-à-d., c'est le seul moment où les données changent).

pour ce faire, divisez l'adresse courriel en deux colonnes distinctes dans le tableau, email_user et email_domain). Ensuite, vous pouvez soit le diviser dans votre application avant l'insertion/mise à jour ou utiliser un déclencheur (ou des colonnes pré-calculées si votre SGBD le supporte) dans la base de données pour le faire automatiquement.

Puis vous tri sur email_domain et, lorsque vous voulez l'adresse email complète, vous utilisez email_name|'@'|email_domain.

alternativement, vous pouvez garder le plein email colonne et utilisez un déclencheur pour dupliquer juste la partie du domaine dans email_domain, alors vous n'avez pas besoin de vous soucier de concaténer les colonnes pour obtenir l'adresse email complète.

il est parfaitement acceptable de revenir de 3NF pour des raisons de performance si vous savez ce que vous faites. Dans ce cas, les données des deux colonnes ne peuvent pas être désynchronisées tout simplement parce que les détonateurs ne le permettent pas. C'est un bon moyen d'échanger de l'espace disque (relativement bon marché) pour les performances (nous toujours vous voulez plus de qui).

et, si vous êtes du genre à ne pas aimer revenir du tout de 3NF, le email_name/email_domain solution de résoudre ce problème.

ceci suppose aussi que vous voulez simplement gérer les adresses e-mail du formulaire a@b - il y a d'autres adresses email valides, mais je ne me souviens pas les avoir vues dans la nature pour an.

8
répondu paxdiablo 2010-08-04 22:25:36

pour SQL Server, vous pouvez ajouter un colonne calculée à votre table avec des extraits du domaine dans un champ séparé. Si vous persistez cette colonne dans la table, vous pouvez l'utiliser comme n'importe quel autre champ et même mettre un index dessus, pour accélérer les choses, si vous interrogez par nom de domaine beaucoup:

ALTER TABLE Table1
  ADD DomainName AS 
     SUBSTRING(email, CHARINDEX('@', email)+1, 500) PERSISTED

donc maintenant votre table aurait une colonne supplémentaire "nom de domaine" qui contient n'importe quoi après le signe " @ " dans votre adresse e-mail.

4
répondu marc_s 2009-11-28 08:11:01

en supposant que vous devez vraiment satisfaire MySQL, Oracle et MSSQL .. le moyen le plus efficace pourrait être de stocker le nom du compte et le nom de domaine dans deux champs distincts. Vous pouvez faire votre commande:

select id,name,email from table order by name

select id,name,email,account,domain from table order by email

select id,name,email,account,domain from table order by domain,account

comme donnie le fait remarquer, les fonctions de manipulation de chaîne ne sont pas standard .. c'est pourquoi vous devez conserver les données redondantes!

j'ai ajouté le compte et le domaine à la troisième requête, puisque je me couche pour rappeler que tous les DBMSs ne trient pas une requête sur un champ qui n'est pas les champs sélectionnés.

2
répondu lexu 2009-11-28 04:39:30

Pour postgres la requête est:

SELECT * FROM table
ORDER BY SUBSTRING(email,(position('@' in email) + 1),252)

La valeur 252 est le domaine le plus long autorisé (puisque, la longueur maximale d'un email est 254 y compris la partie locale, le @, et le domaine.

Voir ce pour plus de détails: Quelle est la longueur maximale d'une adresse de courriel valide?

2
répondu zachaysan 2016-02-24 14:29:50

vous allez devoir utiliser les fonctions de manipulation de texte pour analyser le domaine. Puis commandez par la nouvelle colonne.

1
répondu monksy 2009-11-28 04:23:11

MySQL, une combinaison intelligente de droite() et instr ()

SQL Server,droite() et patindex ()

Oracle, instr () et substr ()

et, comme l'a dit quelqu'un d'autre, si vous avez un décent à haut nombre de disques, envelopper votre champ d'e-mail dans des fonctions en vous où la clause le fera de sorte que le RDBMS ne peut pas utiliser n'importe quel index que vous pourriez avoir sur cette colonne. Donc, vous pouvez envisager de créer une colonne calculée qui détient le domaine.

1
répondu Donnie 2009-11-28 04:27:55

si vous avez des millions d'enregistrements, je vous suggère de créer une nouvelle colonne avec le nom de domaine seulement.

1
répondu YOU 2009-11-28 04:28:26

cela fonctionnera avec Oracle:

select id,name,email,substr(email,instr(email,'@',1)+1) as domain
from table1
order by domain asc
1
répondu P Sharma 2014-04-28 13:20:08

Ma suggestion serait (pour mysql):

SELECT 
    LOWER(email) AS email,
    SUBSTRING_INDEX(email, '@', + 1) AS account,
 REPLACE(SUBSTRING_INDEX(email, '@', -1), CONCAT('.',SUBSTRING_INDEX(email, '.', -1)),'') -- 2nd part of mail - tld.
  AS domain,
    CONCAT('.',SUBSTRING_INDEX(email, '.', -1)) AS tld
FROM
********
ORDER BY domain, email ASC;
Et puis il suffit d'ajouter un OÙ...
1
répondu Mr_KeyCode 2015-04-14 13:39:58

la réponse originale pour SQL Server ne fonctionnait pas pour moi....

Voici une version pour SQL Server...

select SUBSTRING(email,(CHARINDEX('@',email)+1),len(email)), count(*) 
from table_name 
group by SUBSTRING(email,(CHARINDEX('@',email)+1),len(email))
order by count(*) desc
1
répondu eddievan 2016-06-19 10:24:06

travailler plus intelligemment, pas plus fort:

SELECT REVERSE(SUBSTRING_INDEX(REVERSE(SUBSTRING(emails.email, POSITION('@' IN emails.email)+1)),'.',2)) FROM emails
0
répondu Tarbeya 2012-12-10 05:07:29