Mysql
 sql >> Base de données >  >> RDS >> Mysql

Comment sélectionner les publications créées par moi ou mes amis dans un fil d'actualité ?

Je sais que vous avez déjà accepté une réponse, mais j'étais à mi-chemin de l'écrire, j'ai donc décidé de la publier quand même.

Je vais revenir un peu en arrière avant de répondre à votre question. Lors du développement d'applications et de la construction de bases de données, vous devez TOUJOURS essayez de structurer les choses de la manière la plus descriptive et la plus compacte possible. Il serait vraiment gênant d'avoir une variable/colonne nommée color et y stocker les mots de passe utilisateur cryptés (bizarre, non ?). Il existe certaines conventions standard de dénomination des bases de données qui, lorsqu'elles sont suivies, facilitent grandement la vie, en particulier lors du développement d'applications complexes. Je vous conseille de lire quelques blogs concernant les conventions de nommage. Un bon point de départ peut être ceci un.

Je me rends parfaitement compte qu'avec les modifications suggérées ci-dessous, vous devrez peut-être réécrire partiellement/entièrement le code d'application que vous avez écrit jusqu'à présent, mais c'est à vous de décider si vous voulez vraiment que les choses fonctionnent mieux.

Commençons par fixer la structure de la base de données. À première vue, vous faites une application similaire au fil d'actualité de Facebook. Dans ce cas, en utilisant FOREIGN KEYS est à peu près obligatoire afin que vous puissiez garantir une certaine cohérence des données. L'exemple de schéma de base de données ci-dessous montre comment vous pouvez y parvenir.

-- 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;

Maintenant que cela est corrigé, nous pouvons passer à l'étape suivante - sélectionner le fil d'actualité pour john123 (qui a user_id=1 ). Ceci peut être réalisé avec la requête ci-dessous :

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

Et ici vous pouvez le voir en action dans un sqlfiddle. Comme vous pouvez le voir, juste en structurant mieux la base de données, j'ai éliminé le besoin d'une sous-requête (qui est ce que EXISTS / NOT EXISTS faire selon la docs et EXPLAIN ). De plus, le code SQL ci-dessus serait beaucoup plus facile à maintenir et à étendre.

Quoi qu'il en soit, j'espère que vous trouverez cela utile.