-2

次のテーブルがあります。

members(id, name, surname, username, password)
friends(uid, friend_uid, confirmed_uid, confirmed_friend_uid)

friends テーブルでは、uidとがfriend_uid関係しています。members.idここで、uidは常に より低くなりfriend_uidます。が友達になることに同意したfriends.confirmed場合は true 、友情を確認した場合は trueです。friends.uidfriends.friend_confirmedfriends.friend_uid

ユーザー A は B と C のみのフレンドであり、両方ともフレンドシップを確認しています。B と C のリスト (すべての A の確認済みの友達) を A に表示するクエリが必要ですが、まだ A と友達ではないことを確認しています。

私のMySQLは非常に錆びているので、現在複数のクエリでこれを行っていますが、これは非常に非効率的である必要があり、Webサイトのパフォーマンスに影響を与える前にすべてのクエリを作成する必要があります.

私は MySQL のドキュメントを読み始めました。どこかで入手できたら更新しますが、誰かがプロセスをスピードアップするのを手伝ってくれるなら、大いに感謝します。

これが私が少し疑似コードでそれをやっている方法です:

member_id_for_A = 1;
friends_of_A = mysql_query("
            SELECT m.*, f.* FROM friends f 
            inner join members m on m.id = f.uid 
              WHERE f.friend_uid = " + member_id_for_A + " AND confirmed_uid=1 AND confirmed_friend_uid=1 
            UNION
              SELECT m.*, f.* FROM friends f 
              inner join members m on m.id = f.friend_uid 
                WHERE f.uid = " + member_id_for_A + " AND confirmed_uid=1 AND confirmed_friend_uid=1");

foreach(row : friends_of_A)
{
  friend_id = get_friened_id(row, member_id_for_A);
  friends_of_friend = get_friends(friend_id); // Performs a query like above friends_of_friend
  result = remove_matches(friends_of_A, friends_of_friend); // Remove common friends

  // Do something with results and move onto the next friend
}

これは非常に悪いコードであり、効率的ではないことはわかっていますが、MySQL をさらに学習する時間ができるまで、必要な機能を簡単に手に入れることができるハックな方法でした。1 つのクエリで、私が何を目指しているかを明確に把握できることを願っています。

4

2 に答える 2

0

どうぞ...

select m.id,m.surname,m.name from friends f1
inner join friends f2
on f1.friend_uid=f2.uid      /* Identify friend of friend*/
inner join members m
on m.id=f2.friend_uid       /* Match & get Friend of Friend's User detail */
where f1.confirmed_uid=1         /* Friend1 is confirmed */
and f2.confirmed_friend_uid=1
and m.id <> f2.uid          /* Friend2 is not already a friend */

選択リストで、必須フィールドを選択します

于 2012-11-24T11:34:06.753 に答える
0

サブクエリのドキュメントを見た後、実用的なソリューションを思いつくことができました。

この例では、A にはmembers.id=8.

SELECT * FROM members
WHERE id IN ( 
 SELECT m.id FROM friends f  INNER JOIN members m on m.id=f.uid 
 WHERE f.friend_uid IN ( 
  SELECT m.id FROM friends f  INNER JOIN members m on m.id=f.uid 
  WHERE f.friend_uid=8 AND confirmed_uid=1 AND confirmed_friend_uid=1  
   UNION SELECT m.id FROM friends f  INNER JOIN members m on m.id=f.friend_uid 
   WHERE f.uid=8 AND confirmed_uid=1 AND confirmed_friend_uid=1
 ) AND m.id<>8 AND f.confirmed_uid=1 AND f.confirmed_friend_uid=1 
  UNION SELECT m.id FROM friends f  INNER JOIN members m on m.id=f.uid 
  WHERE f.uid IN ( 
   SELECT m.id FROM friends f INNER JOIN members m on m.id=f.uid 
   WHERE f.friend_uid=8 AND confirmed_uid=1 AND confirmed_friend_uid=1 
    UNION SELECT m.id FROM friends f  INNER JOIN members m on m.id=f.friend_uid
    WHERE f.uid=8 AND confirmed_uid=1 AND confirmed_friend_uid=1
   ) AND m.id<>8 AND f.confirmed_uid=1 AND f.confirmed_friend_uid=1
) AND id NOT IN (
 SELECT m.id FROM friends f  INNER JOIN members m on m.id=f.uid 
 WHERE f.friend_uid=8 AND confirmed_uid=1 AND confirmed_friend_uid=1  
  UNION SELECT m.id FROM friends f  INNER JOIN members m on m.id=f.friend_uid 
  WHERE f.uid=8 AND confirmed_uid=1 AND confirmed_friend_uid=1
); 

このクエリはうまく高速に実行され、A のすべての友人のうち、まだ A の友人ではない友人が返されます。また、関係の両方のメンバーによって友情が確認されていることも確認されます。

同じサブクエリがクエリ全体で 3 つの別々の機会に使用されるため、このクエリのサイズを縮小する方法がある可能性があります。

 SELECT m.id FROM friends f  INNER JOIN members m on m.id=f.uid 
 WHERE f.friend_uid=8 AND confirmed_uid=1 AND confirmed_friend_uid=1  
  UNION SELECT m.id FROM friends f  INNER JOIN members m on m.id=f.friend_uid 
  WHERE f.uid=8 AND confirmed_uid=1 AND confirmed_friend_uid=1

このサブクエリを 1 回だけ実行する方法があれば教えてください。それ以外の場合は、自分で答えを見つけたら編集します。

于 2012-11-26T14:23:32.133 に答える