Pregunta

¿Cuál es la instrucción SQL más corta y / o eficiente para ordenar una tabla con una columna de dirección de correo electrónico por su fragmento de nombre DOMINIO?

Eso esencialmente ignora lo que sea que esté antes de " @ " en las direcciones de correo electrónico y no distingue entre mayúsculas y minúsculas. Ignoremos los nombres de dominio internacionalizados para este.

Destino en: mySQL, MSSQL, Oracle

Datos de muestra 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

Ordenar por correo electrónico
SELECCIONAR * DE LA TABLA 1 ORDENAR POR CORREO ELECTRÓNICO 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

Ordenar por dominio
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

EDITAR:
No estoy pidiendo una sola declaración SQL que funcione en los 3 o más motores SQL. Cualquier contribución es bienvenida. :)

¿Fue útil?

Solución

Prueba esto

Consulta (para servidor SQL):

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

Consulta (para Oracle):

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

Consulta (para MySQL)

pygorex1 already answered

Salida:

nombre de correo electrónico de identificación

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

Otros consejos

Para MySQL:

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

Para mayúsculas y minúsculas:

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

Si desea que esta solución se escale, no debería intentar extraer subcolumnas. Las funciones por fila son notoriamente lentas a medida que la tabla se hace más y más grande.

Lo correcto en este caso es mover el costo de extracción de select (donde sucede mucho) a insert / update donde ocurre menos (en la mayoría de las bases de datos normales). Al incurrir en el costo solo en insert y update , aumenta en gran medida la eficiencia general de la base de datos, ya que ese es el solo momento en el que necesita hacerlo (es decir, es el único momento en que los datos cambian).

Para lograr esto, divida la dirección de correo electrónico en dos columnas distintas en la tabla, email_user y email_domain ). Luego, puede dividirlo en su aplicación antes de la inserción / actualización o usar un activador (o columnas precalculadas si su DBMS lo admite) en la base de datos para hacerlo automáticamente.

Luego ordena en email_domain y, cuando desea la dirección de correo electrónico completa, usa email_name | '@' | email_domain .

Alternativamente, puede mantener la columna email completa y usar un disparador para duplicar solo la parte del dominio en email_domain , luego nunca tendrá que preocuparse por concatenar las columnas a obtener la dirección de correo electrónico completa.

Es perfectamente aceptable revertir de 3NF por razones de rendimiento siempre que sepa lo que está haciendo. En este caso, los datos en las dos columnas no se pueden desincronizar simplemente porque los desencadenantes no lo permiten. Es una buena manera de intercambiar espacio en disco (relativamente barato) por rendimiento ( siempre queremos más de eso).

Y, si eres del tipo al que no le gusta revertir de 3NF, la solución email_name / email_domain lo solucionará.

Esto también supone que solo desea manejar las direcciones de correo electrónico del formulario a @ b : hay otras direcciones de correo electrónico válidas, pero no recuerdo haber visto ninguna de ellas en la naturaleza durante años.

Para SQL Server, puede agregar una columna calculada a su tabla con extractos del dominio en un campo separado. Si persiste esa columna en la tabla, puede usarla como cualquier otro campo e incluso ponerle un índice, para acelerar las cosas, si consulta mucho por nombre de dominio:

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

Entonces, su tabla tendría una columna adicional " DomainName " que contiene cualquier cosa después de " @ " inicie sesión en su dirección de correo electrónico.

Suponiendo que realmente debe atender a MySQL, Oracle y MSSQL ... la forma más eficiente podría ser almacenar el nombre de la cuenta y el nombre de dominio en dos campos separados. El puede hacer su pedido:

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

como señala donnie, las funciones de manipulación de cadenas no son estándar ... ¡es por eso que tendrás que mantener los datos redundantes!

Agregué cuenta y dominio a la tercera consulta, ya que creo que no todos los DBMS ordenarán una consulta en un campo que no está en los campos seleccionados.

Para postgres la consulta es:

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

El valor 252 es el dominio más largo permitido (ya que la longitud máxima de un correo electrónico es 254 incluyendo la parte local, el @ y el dominio.

Vea esto para más detalles: ¿Cuál es el longitud máxima de una dirección de correo electrónico válida?

Tendrá que usar las funciones de manipulación de texto para analizar el dominio. Luego ordene por la nueva columna.

MySQL, una combinación inteligente de right () y instr ()

SQL Server, right () y patindex ()

Oracle, instr () y substr ()

Y, como dijo alguien más, si tiene un recuento de registros decente a alto, ajustando su campo de correo electrónico en funciones donde la cláusula lo hará para que el RDBMS no pueda usar ningún índice que pueda tener en esa columna. Por lo tanto, es posible que desee considerar crear una columna calculada que contenga el dominio.

Si tiene millones de registros, le sugiero que cree una nueva columna solo con el nombre de dominio.

Esto funcionará con Oracle:

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

Mi sugerencia sería (para 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;
Y luego solo agrega un DONDE ...

La respuesta original para SQL Server no funcionó para mí ...

Aquí hay una versión para 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

trabaja de manera más inteligente, no más duro:

SELECT REVERSE(SUBSTRING_INDEX(REVERSE(SUBSTRING(emails.email, POSITION('@' IN emails.email)+1)),'.',2)) FROM emails
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top