SQL: сортировка по имени домена электронной почты

каков самый короткий и / или эффективный оператор SQL для сортировки таблицы со столбцом адреса электронной почты по его фрагменту доменного имени?

это по существу игнорирует все, что находится перед " @ " в адресах электронной почты и без учета регистра. Давайте проигнорируем интернационализированные доменные имена для этого.

Target at: mySQL, MSSQL, Oracle

выборка данных из 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

Порядок Электронная почта
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

Заказать По Домену
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:
Я не прошу ни одного оператора SQL, который будет работать на всех 3 или более SQL-движках. Любой вклад приветствуется. :)

13 ответов


попробуй такое

Запрос (Для Sql Server):

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

Запрос(Для Oracle):

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

запрос(для MySQL)

pygorex1 already answered

выход:

id имя электронной почты

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

Для MySQL:

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

для нечувствительных к регистру:

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

если вы хотите, чтобы это решение все, вам нужно не пытается извлечь вложенные столбцы. Функции в строке, как известно, медленно, как таблица становится все больше и больше.

на право вещь, котор нужно сделать в этом случае двинуть цену извлечения от select (где это происходит много) в insert/update где это происходит меньше (в большинстве обычных баз данных). Взяв на себя расходы только на insert и update, вы значительно увеличиваете общий эффективность базы данных, так как это только момент времени, когда вам нужно это сделать (т. е. это единственное время, когда данные меняются).

для этого разделите адрес электронной почты на два отдельных столбца в таблице,email_user и email_domain). Затем вы можете разделить его в своем приложении перед вставкой / обновлением или использовать триггер (или предварительно вычисленные столбцы, если ваша СУБД поддерживает его) в базе данных, чтобы сделать это автоматически.

затем вы Сортировать по email_domain и, когда требуется полный адрес электронной почты, вы используете email_name|'@'|email_domain.

кроме того, вы можете сохранить полный email столбец и используйте триггер, чтобы дублировать только часть домена в email_domain, тогда вам не нужно беспокоиться о конкатенации столбцов, чтобы получить полный адрес электронной почты.

вполне приемлемо вернуться из 3NF по соображениям производительности, если вы знаете, что делаете. В этом случае данные в двух столбцах не могут выйти из синхронизации просто потому, что триггеры этого не позволяют. Это хороший способ торговать дисковым пространством (относительно дешево) для производительности (мы всегда нужен).

и, если вы из тех, кто не любит возвращаться из 3NF вообще,email_name/email_domain решение исправить это.

это также предполагая, что вы просто хотите обрабатывать адреса электронной почты вида a@b - есть и другие действительные адреса электронной почты, но я не могу вспомнить ни одного из них в дикой природе годы.


для SQL Server можно добавить вычисляемый столбец к вашей таблице с извлечениями домена в отдельное поле. Если вы сохраняете этот столбец в таблице, вы можете использовать его как любое другое поле и даже поместить на него индекс, чтобы ускорить процесс, если вы много запрашиваете доменное имя:

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

Итак, теперь ваша таблица будет иметь дополнительный столбец "DomainName", который содержит что-либо после знака " @ " в вашем адресе электронной почты.


предполагая, что вы действительно должны обслуживать MySQL, Oracle и MSSQL .. наиболее эффективным способом может быть сохранение имени учетной записи и доменного имени в двух отдельных полях. Вы можете сделать ваш заказ:

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

как указывает Донни, функции манипуляции строками нестандартны .. вот почему вам придется сохранить данные избыточными!

Я добавил учетную запись и домен к третьему запросу, так как я шов, чтобы вспомнить не все DBMSs будет сортировать запрос на поле, которое не в выбранных полях.


для postgres запрос:

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

значение 252 является самым длинным разрешенным доменом (так как максимальная длина электронной почты 254 включая местную часть,@, и домен.

Посмотреть подробнее: какова максимальная длина действительного адреса электронной почты?


вам придется использовать функции обработки текста для разбора домена. После того, новая колонка.


MySQL, интеллектуальная комбинация right () и instr ()

SQL Server,справа() и patindex ()

Oracle,instr () и substr ()

и, как сказал кто-то другой, если у вас есть достойный высокий счет записей, обернув поле электронной почты в функции в вас, где предложение сделает его таким образом, РСУБД не может использовать какой-либо индекс, который вы могли бы иметь в этом столбце. Итак, ты может потребоваться создать вычисляемый столбец, содержащий домен.


Если у вас есть миллион записей, я предлагаю вам создать новый столбец с именем домена только.


Это будет работать с Oracle:

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

мое предложение было бы (для 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;
А затем просто добавьте где...

исходный ответ для SQL Server не работал для меня....

вот версия для 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

работать умнее, а не тяжелее:

SELECT REVERSE(SUBSTRING_INDEX(REVERSE(SUBSTRING(emails.email, POSITION('@' IN emails.email)+1)),'.',2)) FROM emails