Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Como selecionar postagens criadas por mim ou meus amigos em um feed de notícias?


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.