Ik weet dat je al een antwoord hebt geaccepteerd, maar ik was halverwege met schrijven, dus besloot ik het toch te posten.
Ik ga een beetje terug voordat ik hopelijk uw vraag beantwoord. Bij het ontwikkelen van applicaties en het bouwen van databases, moet u ALTIJD probeer de zaken zo beschrijvend en compact mogelijk te structureren. Het zou erg onhandig zijn om een variabele/kolom te hebben met de naam color
en sla daar versleutelde gebruikerswachtwoorden op (raar, toch?). Er zijn enkele standaard naamgevingsconventies voor databases die, wanneer ze worden gevolgd, het leven een stuk eenvoudiger maken, vooral bij het ontwikkelen van gecompliceerde applicaties. Ik zou je aanraden om wat blogs te lezen over de naamgevingsconventies. Een goed startpunt kan zijn dit
een.
Ik realiseer me volledig dat je met de onderstaande voorgestelde wijzigingen misschien de applicatiecode die je tot nu toe hebt geschreven gedeeltelijk/volledig moet herschrijven, maar het is aan jou of je echt wilt dat de dingen beter werken.
Laten we beginnen met het repareren van de databasestructuur. Zo te zien doe je een applicatie die lijkt op de nieuwsfeed van Facebook. In dit geval, met behulp van FOREIGN KEYS
is vrijwel verplicht, dus u kunt enige gegevensconsistentie garanderen. Het voorbeelddatabaseschema hieronder laat zien hoe u dat kunt bereiken.
-- 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;
Nu dit is opgelost, kunnen we doorgaan met de volgende stap - het selecteren van de nieuwsfeed voor john123
(wie heeft user_id=1
). Dit kan worden bereikt met de onderstaande vraag:
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
En hier
je zou het in actie kunnen zien in een sqlfiddle. Zoals je kunt zien, heb ik door de database beter te structureren, de noodzaak van een subquery geëlimineerd (wat is wat EXISTS / NOT EXISTS
is) doen volgens de docs en EXPLAIN
). Bovendien zou de bovenstaande SQL-code een stuk eenvoudiger te onderhouden en uit te breiden zijn.
Hoe dan ook, ik hoop dat je dit nuttig vindt.