Eu sei que você já aceitou uma resposta, mas eu estava no meio do caminho para escrever isso, então decidi postar mesmo assim.
Vou voltar um pouco antes de responder sua pergunta. Ao desenvolver aplicativos e construir bancos de dados, você deve SEMPRE tente estruturar as coisas da forma mais descritiva e compacta possível. Seria muito estranho ter uma variável/coluna chamada
color
e armazenar senhas de usuário criptografadas lá (estranho, certo?). Existem algumas convenções de nomenclatura de banco de dados padrão que, quando seguidas, tornam a vida muito mais fácil, especialmente ao desenvolver aplicativos complicados. Eu aconselho você a ler alguns blogs sobre as convenções de nomenclatura. Um bom ponto de partida pode ser isto
1. Compreendo perfeitamente que, com as alterações sugeridas abaixo, talvez seja necessário reescrever parcialmente/totalmente o código do aplicativo que você escreveu até agora, mas depende de você se realmente deseja que as coisas funcionem melhor.
Vamos começar corrigindo a estrutura do banco de dados. Pelo que parece, você está fazendo um aplicativo semelhante ao feed de notícias do facebook. Neste caso, usando
FOREIGN KEYS
é praticamente obrigatório para que você possa garantir alguma consistência de dados. O esquema de banco de dados de exemplo abaixo mostra como você pode conseguir isso. -- 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;
Agora que isso foi corrigido, podemos prosseguir com a próxima etapa - selecionando o feed de notícias para
john123
(que tem user_id=1
). Isso pode ser feito com a consulta abaixo: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
E aqui você pode vê-lo em ação em um sqlfiddle. Como você pode ver, apenas estruturando melhor o banco de dados, eliminei a necessidade de uma subconsulta (que é o que
EXISTS / NOT EXISTS
faça de acordo com os docs e EXPLAIN
). Além disso, o código SQL acima seria muito mais fácil de manter e estender. De qualquer forma, espero que você ache isso útil.