質問

ドメイン名フラグメントで電子メールアドレスの列を持つテーブルをソートするための最短および/または効率的な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ステートメントを要求していません。どんな貢献も歓迎します。 :)

役に立ちましたか?

解決

これを試してください

クエリ(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

他のヒント

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 でのみコストが発生することにより、データベースの全体的な効率が大幅に向上します。それを行う必要があります(つまり、データが変更されるのはそれだけです)。

これを実現するには、メールアドレスをテーブル内の2つの異なる列、 email_user email_domain に分割します)。その後、挿入/更新の前にアプリケーションで分割するか、データベースでトリガー(またはDBMSでサポートされている場合は事前に計算された列)を使用して自動的に実行します。

次に email_domain でソートし、完全なメールアドレスが必要な場合は、 email_name | '@' | email_domain を使用します。

または、 email 列全体を保持し、トリガーを使用して email_domain のドメイン部分のみを複製することができます。列を連結することを心配する必要はありません。完全なメールアドレスを取得します。

何をしているのかわかっていれば、パフォーマンス上の理由から3NFから復帰することは完全に許容できます。この場合、2つの列のデータは、トリガーで許可されていないという理由だけで同期を取ることができません。これは、パフォーマンスのためにディスクスペース(比較的安価)を交換するのに適した方法です(常により多くの機能が必要です )。

そして、もしあなたが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に対応する必要がある場合、最も効率的な方法は、アカウント名とドメイン名を2つの別々のフィールドに保存することです。注文を行うことができます:

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

ドニーが指摘するように、文字列操作関数は標準ではありません..そのため、データを冗長に保つ必要があります!

アカウントとドメインを3番目のクエリに追加しました。すべてのDBMSが選択したフィールドにないフィールドでクエリをソートするわけではないことを思い出してください。

postgresのクエリは次のとおりです。

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

252 は、許可される最長のドメインです(電子メールの最大長は、ローカル部分 @ を含めて 254 であるため、およびドメイン。

詳細については、こちらをご覧ください:有効なメールアドレスの最大長?

ドメインを解析するには、テキスト操作関数を使用する必要があります。次に、新しい列で注文します。

MySQL、 right()のインテリジェントな組み合わせおよび instr()

SQL Server、 right()および patindex()

Oracle、 instr()および substr()

そして、他の誰かが言ったように、レコード数がまともな場合、where句の関数で電子メールフィールドをラップすると、RDBMSはその列にあるインデックスを使用できなくなります。そのため、ドメインを保持する計算列の作成を検討することをお勧めします。

100万件のレコードがある場合は、ドメイン名のみで新しい列を作成することをお勧めします。

これは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;
そして、WHERE ...

を追加するだけです

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
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top