2012-01-23 11 views
8

メンバーレコードのリストを表示しようとしています。私が必要とするものを表示するために使用しているテーブルがいくつかあります。MySQLサブクエリ - LEFT JOINの最初のレコードのみを検索する

これは簡単な部分です。私が必要とするのは、各メンバーレコードのレコードが多いテーブルです。ログイン履歴

ログイン履歴テーブルにある各メンバーレコードの最初の行のみを表示します。また、フロップをフリップしてログイン履歴テーブルの最後のレコードを表示することもできます。期待されているものを返し

SELECT m.memberid, m.membername, m.gender, mp.phone 
FROM tbl_members m, 
    tbl_members_phones mp, 
    tbl_members_addresses ma 
WHERE m.defaultphoneid = mp.phoneid 
AND m.defaultaddressid = ma.addressid 

ので:こちらを

は、私がこれまで持っているものです。

2列tbl_members_login_history返された結果に追加したいのですが:mh。 loggedtime、mh。 ipaddy

私はLEFTとしてtbl_members_login_historyを追加することを知っているが、重複を返すのJOINので、私はtbl_members_login_historyに存在することをmemberidのためのちょうど第一のレコードを返すために、ここでのサブクエリの必要がなければならないと思っています。

私が心配しているのは、履歴テーブルのレコードが存在しない場合でも、そのメンバー情報を表示したいが、履歴列はNULLのままにしておくことです。

これはサブクエリインシデントですか?もしそうなら、そのタイプのLIMITをどのように追加しますか?

+0

メンバーは電話番号と住所が必要ですか?もしそうでなければ、あなたの質問が書かれている方法が欠けている場合、あなたの質問は他のメンバー情報を返すとは思わない。 – Sam

+0

この場合、はい。しかし、あなたが正しいです、メンバーは、既存のレコードなしで結果に返されません。 – coffeemonitor

答えて

20

これはgreatest-n-per-groupの問題で、スタックオーバーフローで頻繁に尋ねられます。ここで

は、私はあなたのシナリオでそれを解決する方法は次のとおりです。

SELECT m.memberid, m.membername, m.gender, mp.phone, mh.loggedtime, mh.ipaddy 
FROM tbl_members m 
INNER JOIN tbl_members_phones mp ON m.defaultphoneid = mp.phoneid 
INNER JOIN tbl_members_addresses ma ON m.defaultaddressid = ma.addressid 
LEFT OUTER JOIN tbl_members_login_history mh ON m.memberid = mh.memberid 
LEFT OUTER JOIN tbl_members_login_history mh2 ON m.memberid = mh2.memberid 
    AND mh.pk < mh2.pk 
WHERE mh2.pk IS NULL; 

つまり、我々はmhが与えられたMEMBERIDためtbl_member_login_historyの中で最も最近の行になりたいです。そこで、さらに最近の行mh2を検索します。 mh行より新しいものが見つからない場合、mh2.*はNULLになるので、mhが最新のものでなければなりません。

このテーブルには、増加する値を含む主キー列があるとします。この例では、列名がpkと仮定します。

に対してLEFT OUTER JOINを使用するログイン履歴テーブルへの参照は、一致する行がない場合でもm行が報告されることを意味します。

+0

あなたのソリューションを試してみましたが、 'GROUP BY'と' MAX(...) 'を使ってサブクエリを含むクエリと比較し、 'ON date = maxdate'に合流しました。サブクエリ解が0.01s(もちろん同じ結果表)であったのに対し、 '<'演算子を持つあなたの解は2s(!)でした。あなたのクエリの 'EXPLAIN'はサブクエリを持つものよりもはるかによく見えます。なぜ私はこの巨大なパフォーマンスの違いを得るのか分かりませんが、 '<'は巨大な中間結果を生み出すためです。 – steffen

+0

@steffen:私はこの質問に答えて以来、私は他の多くのケースを見てきました。上記の解決策またはあなたのような解決策は、いくつの異なるグループといくつのデータが持つグループごとの行。したがって、両方のメソッドをデータでテストしてから決定するのが最善です。 –

+0

真。私を混乱させたのはパフォーマンスの大きな違いでした。私はあなたの解決策をここで数回見つけました。そして、 'EXPLAIN'出力はすばらしく見えるので、私はそのクエリが非常に速くなることを期待していました。しかし、それはずっと遅かったです。奇妙な。 – steffen

0

この

LEFT OUTER JOIN (SELECT member_id, MAX(LAST_LOGIN_DATE) from tbl_members_login_history) Last_Login ON Last_Login.memberid = m.memberid 

PSのように追加します。 LAST_LOGIN_DATEは擬似列で、あなたのrestictiveカラムを試すことができます

関連する問題