2009-03-03 57 views
0

名前とメールの名前がname_emailの単純なテーブルがあります。個別のSQLクエリ

私はそのようそれからデータを取得しようとしています:、同じ名前を持つ 2の場合の行が、一つは「@ yahoo.com」で終わるされた電子メールを持ち、もう一方は別の電子メールを持っています「@ yahoo.com」の電子メールを含むものは破棄する必要があります。

このデータを取得するにはどうすればよいでしょうか?

答えて

3

さて、私は、データベースのスキーマの変更を提唱べきではないと言う人たちとのまた別の戦いに巻き込まするつもりはない(そう、あなたが:-)誰であるか知っているが、ここで私はそれを行うだろう方法です。

1 /あなたが絶対にスキーマを変更できない場合は、コードで解決します(DBMSが許可する任意の言語のストアドプロシージャまたは正式な正直さの手続きコード)。

これは、データベースにyahoo以外の名前がないかどうかをチェックし、もしあればそれを返します。そこになければ、ヤフー名を返そうとします。どちらも存在しない場合は、空のデータセットが返されます。

2 /スキーマを変更することができますし、あなたが仕事をするために、SQLクエリをしたい場合は、ここで私はそれを行うだろう方法です。 CLASSという名前の別の列をテーブルに作成します。この列は、非Yahooアドレス用に0、Yahooアドレス用に1に設定されています。

挿入/更新を作成したメールアドレス(それで終わるもの)に基づいて、クラスを設定し、各付加または行の変化を調べるためにトリガー。これによりCLASSは常に正しく設定されます。

テーブルをクエリするときは、名前とクラスで並べ替え、最初の行のみを選択します。これは、非ヤフー、ヤフー、空のデータセットの電子メールアドレスをあなたに提供します。以下のよう

何か:あなたのDBMSがDB2に相当するものを持っていない場合

select name, email 
from tbl 
where name = '[name]' 
order by name, class 
fetch first row only; 

句「だけを最初の行をフェッチ」、あなたはおそらくまだ唯一のプロセス1つのレコードにコードを記述する必要があります。

この名前の特定の電子メールのみを処理したい場合は、このようなプログラムで十分です(手順的な方法でSQLなどのリレーショナル代数を使用しようとすると私の見解はかなり残忍です。私は)ここに、あなたにそれらを与えません。

# Get entire table contents sorted in name/class order. 
resultSet = execQuery "select name, email from tbl order by name, class" 

# Ensure different on first row 
lastName = resultSet.value["name"] + "X" 

# Process every single row returned. 
while not resultSet.endOfFile: 
    # Only process the first in each name group (lower classes are ignored). 
    if resultSet.value["name"] != lastName: 
     processRow resultSet.value["name"] resultSet.value["email"] 
    # Store the last name so we can detect next name group. 
    lastName = resultSet.value["name"] 
+0

これはこの問題を解決する正しい方法です。 – kquinn

0

無効な電子メールアドレスを除外するために、次のような何かを使用することができます

SELECT name, email 
FROM name_email 
WHERE email NOT LIKE '%@yahoo.com' // % symbol is a wildcard so [email protected] and [email protected] both match this query. 
AND name = 'Joe Guy'; 

それとも唯一の有効な電子メールアドレスまたはドメインを含めるには、このようにそれを行うの:

SELECT name, email 
FROM name_email 
WHERE email LIKE '%@gmail.com' 
AND name = 'Joe Guy'; 

これがあればうまく機能あなたはあなたが照会している特定の名前と、除外または含める電子メールアドレスまたはドメインを事前に知っています。

それとも、あなたは返すが、一つだけを返すようにしたいメールアドレス気にしないならば、あなたはこのようなもの使用することができます

SELECT DISTINCT (name, email) 
FROM name_email; 
+0

thatsのことです。私は時間の前に名前を知っていない:)私は重複する名前を探しています。 – Omnipresent

+0

DISTINCT演算子を使用して2番目の方がうまく動作しますか? –

+0

2つの電子メールアドレスを持つすべての名前が常にx電子メールアドレスを返すような追加基準がある場合は、それを反映するために質問を編集してください。 –

0

をあなたは

SELECT TOP 1 email 
FROM name_email 
WHERE name = 'Joe Guy' 
ORDER BY case when email like '%yahoo.com' then 1 else 0 end 

を行うことができますので、それらを並べ替えます*@yahoo.comで最後に何か他のものを最初に取ってください。

EDIT:申し訳ありませんが、質問を読み違える - あなただけの1つの電子メール、および非ヤフーメールを優先して、それぞれの名前のリストが欲しいです。おそらくグループと一緒に上記を使用することができます、私はそれを再考する必要があります。

+0

これはうまくいくだろうが、私はselect-side per-row処理の大きなファンではない。これは、別の列を使用してトリガーする必要がある種類のものです。私の経験のほとんどのテーブルは、書かれたものよりずっと頻繁に読み込まれます。並べ替え順序を設定する挿入/更新側のプロセスがより良いIMNSHOです:-)。 – paxdiablo

+0

これは私のメインフレームのバックグラウンドと関係しています。私たちの構成テーブルでさえも、それらの「より小さい」データベースのトランザクションテーブルを矮小化します:-) – paxdiablo

0

は、データベースからすべての行をつかむの名前が(と)本当にそれを気にする必要はないされているものではありません知っているが、ちょうどそれらを表示したいです、一致する場合は、メールが含まれている場合は一致するものをスキップします。この場合、@ yahoo.com

SELECT DISTINCT name, email FROM name_email 
    WHERE email NOT LIKE '%@yahoo.com' 
    GROUP BY name; 

これを行うと、すべての行が取得されますが、名前が別の行と一致する場合はレコードの1つだけが取得されます。しかし、名前が一致する2つの行がある場合は、メールに@ yahoo.comという名前のファイルをジャンクします。

+0

名前でグループ化した場合、min(email)のような集計関数を持つ必要があります また、その人が1つの電子メールしか持っておらず、yahoo電子メールであれば返信したいと考えています。重複があり、そのうちの1つが他のものを望むyahooである場合に限ります。 – MikeW

+0

OPQは、彼があらかじめ知っていない名前に基づいてすべての異なる行を取りたいと思うように読み込みます。同じ名前の行の場合、使用している電子メールを確認するためにチェックします。そのうちの1人がyahoo.comと一緒にいる場合は、それを捨てて非Yahooのものを表示してください。 – random

1
select ne.* 
from name_email ne 
where ne.email not like '%@yahoo.com' escape '\' or 
    not exists(
       select 1 from name_email 
       where name = ne.name and 
       email not like '%@yahoo.com' escape '\' 
      ) 
0

ない非常にきれいな、私はそれが重複した電子メールがyahoo.comドメインにあるであろうことを想定している

select 
    ne.name 
    ,ne.email 
from 
    name_email ne 
    inner join (
     select 
      name 
      ,count(*) as emails_per_name 
     from 
      name_email 
     group by name 
    ) nec 
     on ne.name = nec.name 
where 
    nec.emails_per_name = 1 
    or (nec.emails_per_name > 1 and ne.email not like ('%@yahoo.com')) 

動作するはずと信じて - あなたの質問に指定されているように、そしてそれらは除外されます名前ごとに複数の電子メールがある場合

0

SQL Server 2005またはOracleを使用している場合は、ランク付け(分析)機能を使用して問題を簡単に解決できます。あなたも「好み」を持つことができ、様々な一般的な電子メール名に異なる値を割り当てることにより

select a.name, a.name_email 
from (select name, name_email, 
      row_number() over (partition by name 
           order by case 
              when name_email like '%@yahoo.com' then 1 
              when name_email like '%@gmail.com' then 1 
              when ... (other 'generic' email) then 1 
              else 0 
             end) as rn) as a 
where a.rn = 1 

。ここに書かれているように、あなたがyahooとgmailの両方のアドレスを持っている場合、どちらがピックアップされるのか予測できません。

0

これにはUNIONを使用できます。 yahoo.comなしですべてを選択し、最初のリストにないyahoo.comを持つレコードを選択するだけです。

name_emailしない '%yahoo.com' UNIONが名前NOT INは(テーブルからDISTINCT(名前、name_email)を選択しTABLE は異なる(名前、name_email)を選択し TABLE は異なる(名前、name_email)を選択 WHERE name_email NOT '%yahoo.com')