Question

Quelle est l'instruction SQL la plus courte et / ou la plus efficace pour trier une table avec une colonne d'adresse électronique en fonction de son fragment de nom DOMAIN?

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

Ciblez à: MySQL, MSSQL, Oracle

Exemple de données à partir 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

Commande par courrier électronique
SELECT * FROM TABLE1 COMMANDER PAR 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

Trier 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

MODIFIER:
Je ne demande pas une seule instruction SQL qui fonctionnera sur les 3 moteurs SQL ou plus. Toute contribution est la bienvenue. :)

Était-ce utile?

La solution

Essayez ceci

Requête (pour SQL Server):

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

Requête (pour Oracle):

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

Requête (pour MySQL)

pygorex1 already answered

Sortie:

email nom d'utilisateur

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

Autres conseils

Pour MySQL:

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

Pour la casse:

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

Si vous souhaitez que cette solution évolue, vous ne devriez pas essayer d'extraire des sous-colonnes. Les fonctions par ligne sont notoirement lentes car la table devient de plus en plus grande.

Dans ce cas, la droite chose à faire est de déplacer le coût d'extraction de select (où cela se produit souvent) vers insert / update où il se produit moins (dans la plupart des bases de données normales). En assumant les coûts uniquement sur insert et update , vous augmentez considérablement l'efficacité globale de la base de données, car il s'agit du seul point besoin de le faire (c’est-à-dire que c’est le seul moment où les données changent).

Pour ce faire, divisez l'adresse électronique en deux colonnes distinctes dans la table, utilisateur_email et domaine_email ). Vous pouvez ensuite le scinder dans votre application avant l'insertion / la mise à jour ou utiliser un déclencheur (ou des colonnes pré-calculées si votre SGBD le prend en charge) dans la base de données pour le faire automatiquement.

Ensuite, vous effectuez un tri sur domaine_email et, lorsque vous souhaitez obtenir l'adresse électronique complète, vous utilisez nom_email | '@' | domaine_email .

Vous pouvez également conserver la colonne email et utiliser un déclencheur pour dupliquer uniquement la partie de domaine dans domaine_email . Vous n'aurez donc jamais à vous soucier de la concaténation des colonnes. obtenir l'adresse e-mail complète.

Il est parfaitement acceptable de revenir de 3NF pour des raisons de performances, à condition que vous sachiez ce que vous faites. Dans ce cas, les données des deux colonnes ne peuvent pas être désynchronisées simplement parce que les déclencheurs ne le permettent pas. C'est un bon moyen d'échanger de l'espace disque (relativement bon marché) contre des performances (nous toujours voulons plus que cela).

Et si vous n'aimez pas du tout revenir à 3NF, la solution email_name / email_domain résoudra ce problème.

Cela suppose également que vous souhaitiez simplement gérer les adresses électroniques de la forme a @ b - il existe d'autres adresses électroniques valides, mais je ne me souviens pas en avoir vu l'une à l'état sauvage pendant des années.

Pour SQL Server, vous pouvez ajouter une colonne calculée à votre table en extrayant le domaine dans un champ séparé. Si vous conservez cette colonne dans la table, vous pouvez l'utiliser comme n'importe quel autre champ et même y mettre un index pour accélérer les choses, si vous interrogez beaucoup par nom de domaine:

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

Votre table aurait alors une colonne supplémentaire "quotName". qui contient quelque chose après "& @" connectez-vous à votre adresse e-mail.

En supposant que vous deviez vraiment gérer MySQL, Oracle et MSSQL .. le moyen le plus efficace pourrait consister à stocker le nom du compte et le nom du domaine dans deux champs distincts. Le 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 le souligne donnie, les fonctions de manipulation des chaînes ne sont pas standard .. C’est pourquoi vous devrez conserver les données redondantes!

J'ai ajouté un compte et un domaine à la troisième requête, car je me sers pour rappeler tous les SGBD ne trieront pas une requête sur un champ qui ne figure pas dans les champs sélectionnés.

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é (car la longueur maximale d'un e-mail est 254 , y compris la partie locale, le @ et le domaine.

Voir ceci pour plus de détails: Quel est le longueur maximale d'une adresse e-mail valide?

Vous allez devoir utiliser les fonctions de manipulation de texte pour analyser le domaine. Ensuite, commandez par la nouvelle colonne.

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

SQL Server, right () et patindex ()

Oracle, instr () et substr ()

Et, comme l’a dit quelqu'un d'autre, si vous avez un nombre d'enregistrements décent à élevé, le fait de placer votre champ d'e-mail dans des fonctions vous permettant de ne pas utiliser d'index dans cette colonne. Vous pouvez donc envisager de créer une colonne calculée contenant le domaine.

Si vous avez des millions d'enregistrements, je vous suggère de créer une nouvelle colonne avec un nom de domaine uniquement.

Ceci fonctionnera avec Oracle:

select id,name,email,substr(email,instr(email,'@',1)+1) as domain
from table1
order by domain asc

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 ajoutez simplement un WHERE ...

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

travaillez plus intelligemment, pas plus fort:

SELECT REVERSE(SUBSTRING_INDEX(REVERSE(SUBSTRING(emails.email, POSITION('@' IN emails.email)+1)),'.',2)) FROM emails
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top