あなたはすでに答えを受け入れていると思いますが、私はこれを書いている途中だったので、とにかく投稿することにしました。
うまくいけばあなたの質問に答える前に、少し戻って行きます。アプリケーションを開発してデータベースを構築するときは、常に 可能な限り説明的でコンパクトなものを構成するようにしてください。 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コードは、保守と拡張がはるかに簡単になります。
とにかく、これがお役に立てば幸いです。