sql >> データベース >  >> RDS >> Mysql

ニュースフィードで私または私の友人によって作成された投稿を選択するにはどうすればよいですか?

    あなたはすでに答えを受け入れていると思いますが、私はこれを書いている途中だったので、とにかく投稿することにしました。

    うまくいけばあなたの質問に答える前に、少し戻って行きます。アプリケーションを開発してデータベースを構築するときは、常に 可能な限り説明的でコンパクトなものを構成するようにしてください。 colorという名前の変数/列があるのは本当に厄介です 暗号化されたユーザーパスワードをそこに保存します(奇妙ですよね?)。いくつかの標準的なデータベースの命名規則があります。これに従うと、特に複雑なアプリケーションを開発するときに、作業がはるかに簡単になります。命名規則に関するいくつかのブログを読むことをお勧めします。良い出発点は、これ 1つ。

    以下の提案された変更により、これまでに作成したアプリケーションコードを部分的/完全に書き直す必要があるかもしれないことを完全に理解していますが、本当にうまく機能させたいかどうかはあなた次第です。

    データベース構造を修正することから始めましょう。見た目では、Facebookのニュースフィードに似たアプリケーションを実行しています。この場合、FOREIGN KEYSを使用します ある程度のデータの一貫性を保証できるように、これはほとんど必須です。以下のデータベーススキーマの例は、それを実現する方法を示しています。

    -- Application users are stored here.
    CREATE TABLE users (
      user_id      INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
      first_name   VARCHAR(255),
      last_name    VARCHAR(255),
      profile_name VARCHAR(255)
    ) ENGINE=InnoDb;
    
    -- User friendship relations go here
    CREATE TABLE friends (
      friend_id   INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
      profile_one INT NOT NULL,
      profile_two INT NOT NULL,
      FOREIGN KEY (profile_one) REFERENCES users (user_id),
      FOREIGN KEY (profile_two) REFERENCES users (user_id)
    ) ENGINE=InnoDb;
    
    -- User status updates go here
    -- This is what will be displayed on the "newsfeed"
    CREATE TABLE statuses (
      status_id    INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
      author_id    INT NOT NULL,
      recipient_id INT NOT NULL,
      message      TEXT,
      -- created date ?
      -- last updated date ?
      FOREIGN KEY (author_id)    REFERENCES users (user_id),
      FOREIGN KEY (recipient_id) REFERENCES users (user_id)
    ) ENGINE=InnoDb;
    
    -- Replies to user statuses go here. (facebook style..)
    -- This will be displayed as the response of a user to a certain status
    -- regardless of the status's author.
    CREATE TABLE replies (
      reply_id  INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
      status_id INT NOT NULL,
      author_id INT NOT NULL,
      message   TEXT,
      FOREIGN KEY (status_id) REFERENCES statuses (status_id),
      FOREIGN KEY (author_id) REFERENCES users    (user_id)
    ) ENGINE=InnoDb;
    

    これが修正されたので、次のステップに進むことができます-john123のニュースフィードを選択します (user_id=1を持っている人 )。これは、以下のクエリで実現できます:

    SET @search_id:=1; -- this variable contains the currently logged in user_id so that we don't need to replace the value more than once in the whole query.
    
    SELECT 
        statuses.*,
        author.first_name     AS author_first_name,
        author.last_name      AS author_last_name,
        recipient.first_name  AS recipient_first_name,
        recipient.last_name   AS recipient_last_name
    FROM statuses
    JOIN users AS author      ON author.user_id    = statuses.author_id
    JOIN users AS recipient   ON recipient.user_id = statuses.recipient_id
    WHERE (statuses.author_id = @search_id OR statuses.recipient_id = @search_id)
    ORDER BY status_id ASC
    

    そして、ここ sqlfiddleで実際に動作しているのを見ることができます。ご覧のとおり、データベースをより適切に構成することで、サブクエリ(EXISTS / NOT EXISTS)の必要性を排除しました。 ドキュメント およびEXPLAIN )。さらに、上記のSQLコードは、保守と拡張がはるかに簡単になります。

    とにかく、これがお役に立てば幸いです。



    1. ClusterControl:新しいクエリモニターの概要

    2. MySQLテーブルの主キーの質問?

    3. mysqlテーブルの同じ列からカウントを取得しますか?

    4. INオペレーターはOracleでLIKEワイルドカード(%)を使用できますか?