SQL:按电子邮件域名排序

时间:2009-11-28 04:15:54

标签: sql sorting email sql-order-by domain-name

使用DOMAIN名称片段对具有一列电子邮件地址的表进行排序的最短和/或最有效的SQL语句是什么?

这基本上忽略了电子邮件地址中“@”之前的内容并且不区分大小写。让我们忽略这个国际化的域名。

目标: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

修改
我不是要求一个可以在所有3个或更多SQL引擎上运行的SQL语句。欢迎任何贡献。 :)

13 个答案:

答案 0 :(得分:19)

试试这个

查询(适用于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 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

答案 1 :(得分:17)

对于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;

答案 2 :(得分:8)

如果您希望此解决方案完全扩展,则尝试提取子列。随着表越来越大,每行函数的速度非常慢。

在这种情况下要执行的正确的事情是将提取成本从select(发生了很多)发送到insert/update,在那里它发生的更少(在大多数正常数据库)。通过仅在insertupdate上产生费用,您可以大大提高数据库的整体效率,因为这是唯一的时间点,您需要这样做(即,这是数据发生变化的唯一时间。)

要实现此目的,请将电子邮件地址拆分为表格email_useremail_domain)中的两个不同列。然后,您可以在插入/更新之前将其拆分到应用程序中,或者在数据库中使用触发器(如果您的DBMS支持,则使用预先计算的列)自动执行此操作。

然后您对email_domain进行排序,当您需要完整的电子邮件地址时,可以使用email_name|'@'|email_domain

或者,您可以保留完整的email列并使用触发器仅复制email_domain中的域部分,然后您无需担心连接列以获取完整的电子邮件地址。

如果您知道自己在做什么,出于性能原因从3NF恢复是完全可以接受的。在这种情况下,两列中的数据不能仅仅因为触发器不允许它而不同步。这是交换磁盘空间(相对便宜)以获得性能的好方法(我们总是想要更多)。

而且,如果你不喜欢从3NF恢复,email_name/email_domain解决方案将解决这个问题。

这也假设您只想处理a@b表单的电子邮件地址 - 还有其他有效的电子邮件地址,但我记不起在野外看到它们中的任何一个。

答案 3 :(得分:4)

对于SQL Server,您可以向表中添加计算列,并将域提取到单独的字段中。如果您将该列保留在表中,您可以像使用任何其他字段一样使用它,甚至可以在其上添加索引,以加快速度,如果您通过域名进行大量查询:

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

所以现在你的表会有一个额外的列“DomainName”,它包含你电子邮件地址中“@”后面的任何内容。

答案 4 :(得分:2)

假设你真的必须迎合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
正如donnie指出的那样,字符串操作函数是非标准的...这就是为什么你必须保持数据冗余!

我已经在第三个查询中添加了帐户和域,因为我联系回忆起并非所有DBMS都会对不在所选字段中的字段进行查询排序。

答案 5 :(得分:2)

对于postgres,查询是:

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

252是允许的最长域名(因为,电子邮件的最大长度为254,包括本地部分,@和域。

详情请见What is the maximum length of a valid email address?

答案 6 :(得分:1)

您将不得不使用文本操作函数来解析域。然后按新列排序。

答案 7 :(得分:1)

MySQL,right()instr()

的智能组合

SQL Server,right()patindex()

Oracle,instr()substr()

而且,正如其他人所说的那样,如果你有一个不错的记录计数,那么将你的电子邮件字段包装在where where子句中的函数中就可以使得RDBMS不能使用你在该列上可能拥有的任何索引。因此,您可能需要考虑创建一个包含域的计算列。

答案 8 :(得分:1)

如果您有百万条记录,我建议您创建仅包含域名的新列。

答案 9 :(得分:1)

这适用于Oracle:

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

答案 10 :(得分:1)

我的建议是(对于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;



 然后只需添加一个WHERE ...

答案 11 :(得分:1)

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

答案 12 :(得分:0)

更聪明地工作而不是更难:

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