sql >> Databáze >  >> RDS >> Mysql

Jak vybrat příspěvky vytvořené mnou nebo mými přáteli v informačním kanálu?

Vím, že jste již přijali odpověď, ale byl jsem v polovině psaní tohoto článku, takže jsem se rozhodl to přesto zveřejnit.

Než snad odpovím na vaši otázku, vrátím se trochu zpět. Při vývoji aplikací a sestavování databází byste měli VŽDY pokuste se věci strukturovat co nejpopisněji a nejkompaktněji. Bylo by opravdu nepříjemné mít proměnnou/sloupec s názvem color a ukládat tam zašifrovaná uživatelská hesla (divné, že?). Existují některé standardní konvence pojmenovávání databází, které, když se dodržují, značně usnadňují život, zvláště při vývoji složitých aplikací. Doporučil bych vám přečíst si nějaké blogy týkající se konvencí pojmenování. Dobrým výchozím bodem může být toto jeden.

Plně si uvědomuji, že s navrhovanými změnami níže možná budete muset částečně/úplně přepsat kód aplikace, který jste dosud napsali, ale je na vás, jestli opravdu chcete, aby věci fungovaly lépe.

Začněme opravou struktury databáze. Podle vzhledu děláte aplikaci podobnou facebookovému newsfeedu. V tomto případě pomocí FOREIGN KEYS je do značné míry povinný, takže můžete zaručit určitou konzistenci dat. Níže uvedené vzorové schéma databáze ukazuje, jak toho můžete dosáhnout.

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

Nyní, když je toto opraveno, můžeme pokračovat dalším krokem – výběrem kanálu zpráv pro john123 (kdo má user_id=1 ). Toho lze dosáhnout pomocí níže uvedeného dotazu:

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

A zde mohli jste to vidět v akci v sqlfiddle. Jak vidíte, lepší strukturou databáze jsem eliminoval potřebu poddotazu (což je to, co EXISTS / NOT EXISTS postupujte podle dokumentů a EXPLAIN ). Navíc výše uvedený kód SQL by bylo mnohem jednodušší udržovat a rozšiřovat.

Každopádně doufám, že to pro vás bude užitečné.



  1. Dotaz MySQL na dynamické řádky hodnocení

  2. přidat sloupec do tabulky mysql, pokud neexistuje

  3. Omezení dotazu na jeden záznam zlepšuje výkon

  4. Je INSERT RETURNING zaručeno, že vrátí věci ve správném pořadí?