sql >> Base de Datos >  >> RDS >> Mysql

¿Cómo seleccionar publicaciones creadas por mí o por mis amigos en un feed de noticias?

Sé que ya aceptaste una respuesta, pero estaba a mitad de camino de escribir esto, así que decidí publicarlo de todos modos.

Voy a retroceder un poco antes de responder a su pregunta. Al desarrollar aplicaciones y construir bases de datos, debe SIEMPRE trata de estructurar las cosas de la manera más descriptiva y compacta posible. Sería muy incómodo tener una variable/columna llamada color y almacenar contraseñas de usuario encriptadas allí (raro, ¿verdad?). Hay algunas convenciones estándar de nomenclatura de bases de datos que, cuando se siguen, hacen la vida mucho más fácil, especialmente cuando se desarrollan aplicaciones complicadas. Le aconsejaría que lea algunos blogs sobre las convenciones de nomenclatura. Un buen punto de partida puede ser esto uno.

Soy plenamente consciente de que, con los cambios sugeridos a continuación, es posible que deba reescribir parcial o totalmente el código de la aplicación que ha escrito hasta ahora, pero depende de usted si realmente desea que las cosas funcionen mejor.

Comencemos arreglando la estructura de la base de datos. Por lo que parece, estás haciendo una aplicación similar a las noticias de Facebook. En este caso, usando FOREIGN KEYS es bastante obligatorio, por lo que podría garantizar cierta consistencia de datos. El siguiente esquema de base de datos de ejemplo muestra cómo puede lograrlo.

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

Ahora que esto está solucionado, podemos continuar con el siguiente paso:seleccionar el suministro de noticias para john123 (que tiene user_id=1 ). Esto se puede lograr con la siguiente consulta:

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

Y aquí podrías verlo en acción en un sqlfiddle. Como puede ver, con solo estructurar mejor la base de datos, eliminé la necesidad de una subconsulta (que es lo que EXISTS / NOT EXISTS hazlo de acuerdo con los docs y EXPLAIN ). Además, el código SQL anterior sería mucho más fácil de mantener y ampliar.

De todos modos, espero que encuentres esto útil.