0

これは少しややこしい質問かもしれません。誰が投稿を表示できるかを決定する列 Permission を持つユーザー投稿のテーブルがあります: 0 = パブリック、1 = サブスクライバーのみ、2 = 連絡先のみ。

列 Subscriber_ID と Subscribed_to_ID を持つ別のテーブル "subscriptions" と、列 User1_ID と User2_ID を持つさらに別のテーブル "contacts" があります。

複雑な MySQL クエリの経験はあまりありません。通常は基本的なクエリしか必要ありませんが、私がやろうとしていることは次のとおりです。

次の条件下で、posts テーブルから投稿を選択する方法を探しています。

  1. ユーザーがサブスクライブしておらず、投稿者の連絡先でもない場合は、公開投稿 (許可が 0 のもの) のみを返します。
  2. ユーザーが投稿の作成者を購読している場合は、0 または 1 のアクセス許可を持つ投稿を返します
  3. ユーザーが連絡先 (自動的にサブスクライブ) の場合、0、1、または 2 の Permission 値を持つ投稿を返します。

構文が正しくないことはわかっていますが、これはこれを行うための良い方法に少しでも近いですか? また、通常は一度に 1 つのテーブルしか操作しないので、混乱しています。これら 3 つのテーブルを結合する必要がありますか?

SELECT user_id, 
       * 
FROM   posts 
WHERE  privacy < IF (user_id IN(SELECT * 
                                FROM   contacts 
                                WHERE  user1_id = 'TestUser' 
                                        OR user2_id = 'TestUser'), 2, 
                 IF ( 
                                  user_id IN (SELECT subscribed_to_id 
                                              FROM   subscriptions 
                                              WHERE  subscriber_id = 'TestUser') 
                 , 
                 1, 0) 
                        ) 

繰り返しますが、私は自分が遠く離れていることを知っていますが、私が慣れ親しんでいる基本的なものよりも複雑な MySQL を学びたいので、誰かがこのクエリを改善する方法についてアドバイスをくれれば、私は間違いなく感謝します!

4

4 に答える 4

0

これを正しく理解している場合、最初の要件は次のようになると思います。

SELECT user_id, *
FROM posts P
LEFT OUTER JOIN subscriptions S
ON P.user_id = S.Subscribed_To_ID
LEFT OUTER JOIN contacts C
ON C.User1_ID = P.user_id
WHERE S.Subscribed_To_ID IS NULL
AND C.User1_ID IS NULL
AND P.Privacy = 0

次に、さらに 2 つの SELECT ステートメントを作成し、それらを UNION していただけますか?

于 2013-01-24T21:22:13.403 に答える
0

関数を使用して、生活を簡素化する必要があります。とにかく完全なテーブルクエリを実行しているため、最適化は問題になりません。

SELECT *
FROM   posts 
WHERE  privacy <= TestPrivacy('TestUser')

CREATE FUNCTION TestPrivacy(CurrentUser VARCHAR(MAX))
BEGIN
DECLARE returnValue INT
   IF ((SELECT COUNT(*) 
      FROM   contacts 
      WHERE  user1_id = CurrentUser
      OR user2_id = CurrentUser) > 0)
   BEGIN
      ReturnValue = 2
   END
   ELSE
   BEGIN
      IF ((SELECT COUNT(*) 
          FROM   subscriptions 
          WHERE  subscriber_id = CurrentUser) > 0) THEN
      BEGIN
         returnValue = 1
      END
      ELSE
      BEGIN
         returnValue = 0
      END
   END

   RETURN returnValue
END
于 2013-01-24T21:24:40.907 に答える
0

これらのテーブルを結合する必要があります。そして、MySQL よりも条件を使用しない方が本当に簡単で、PHP よりも優れています。

これを行う必要がある場合は、この方法で行います。

投稿を選択し、ルールに参加し、サブスクライバーに参加し、ユーザーに参加してから、表示に PHP を使用するか、メッセージを表示しないようにします。

あなたのクエリはちょっと奇妙です。

また、テーブルの結合はそれほど複雑ではありません。

于 2013-01-24T21:21:13.290 に答える
0

これを試して:

select *
  from posts
 where (privacy = 0) /* public */
    or ( /* suscribers */
            (privacy = 1) 
        and (exists (select 1 
                       from subscriptions 
                      where subscriptions.suscriber_id = 'currentuser' 
                        and subscriptions.Subscribed_to_ID = posts.author_id)
            )
       )
    or ( /* contacts: if the user is a contact, doesn't matter the privacy */ 
        exists (select 1
                  from contacts
                 where (contacts.User1_ID = 'currentuser' and contacts.user2_ID = posts.author_id)
                    or (contacts.user2_ID = 'currentuser' and contacts.user1_id = posts.author_id)
        )
       )

私はこれらの仮定に基づいてこれを行いました:

  • ユーザーが表示できるすべての投稿を、すべての作成者から選択したいとします。
  • posts テーブルには、投稿者の user_id を含む author_id という名前の列があります。
  • ビューアーの user_id は既知であり、「currentuser」としてクエリに表示されます。
  • 連絡先テーブルには、連絡先ペアごとに1行しか含まれていないため、where句の二重比較

クエリはブラウザで記述されているため、構文エラーやその他の小さな問題が発生する可能性があります。インデントを見て、適切な括弧の組み合わせを確認してください。

于 2013-01-24T21:43:53.227 に答える