2016-03-25 7 views
4
SELECT * 
    FROM notifications 
    INNER JOIN COMMENT 
    ON COMMENT.id = notifications.source_id 
     WHERE idblog IN (SELECT blogs_id 
     FROM blogs 
     WHERE STATUS = "active") 
    INNER JOIN reportmsg 
    ON reportmsg.msgid = notifications.source_id 
     WHERE uid =: uid 
    ORDER BY notificationid DESC 
    LIMIT 20; 

Hier bin ich INNER JOIN ing notifications mit comment und reportmsg; Dann filtern Inhalt mit WHERE.Was wäre die richtige SELECT-Anweisung dafür?

Aber mein Problem ist, dass für die erste INNER JOIN [das heißt, mit comment], bevor notifications mit comment Beitritt, ich will SELECTnotifications.idblog mit blogs.blogs_idund passen nur die Zeilen, in denen blogs.status = "active".

Zum besseren Verständnis des Codes oben:

ER diagram

hier für INNER JOIN, mit comment Ich möchte SELECT nur die Zeilen in notifications deren idblog Streichhölzer blogs.blogs_idund hat status = "active". Die zweite INNER JOIN mit reportmsg muss nicht geändert werden. Es filtert nur durch uid.

+1

Die Sprache, die Sie mit relationalen Datenbanken zu interagieren wird SQL genannt, nicht PHP. Ich habe deine Frage entsprechend bearbeitet. –

+0

Da 'COMMENT' ein Schlüsselwort ist, wäre ich vorsichtig und setze es um. –

+0

@ bɪɡɪnə überprüfen Sie meine Antwort, ob es erfüllt oder nicht ... und sagen, was ich in meiner Antwort verpasst habe .. – Shiv

Antwort

-1

Sie sollten Ihre Anfrage an das ändern:

SELECT * 
FROM notifications 
INNER JOIN comment ON comment.id = notifications.source_id 
INNER JOIN reportmsg ON reportmsg.msgid=notifications.source_id 
LEFT JOIN blogs ON notifications.idblog = blogs.blogs_id 
WHERE blogs.status = 'active' 
ORDER BY notificationid DESC 
LIMIT 20; 
+0

Danke, aber ich will 'Status = 'aktive'' Bedingung nur für den ersten inneren Beitritt –

+0

Wenn der Rest Ihrer Abfrage funktioniert, aber nur dieser Teil ist nicht, warum stellst du nach der INNER JOIN-Anweisung nicht status = 'active'. So: 'INNER JOIN Kommentar ON comment.id = notifications.source_id UND status = 'active'' –

+0

' "INNER JOIN Kommentar ON (comment.id = notifications.source_id UND comment.status =' active ')" '.. Beachten Sie Ihre Kommentartabelle hat die Statusspalte. –

2

gibt es keine Notwendigkeit/Grund zu Filter vor dem Sekunden kommen, weil Sie nur innere Joins verwenden und dann die Reihenfolge der Joins und WHERE-Bedingungen don‘ t Materie:

SELECT n.*, c.*, r.* 
FROM notifications AS n 
JOIN COMMENT as c 
    ON n.source_id = c.id 
LEFT JOIN blogs as b 
    ON n.idblogs = b.blogs_id 
AND B.STATUS = 'active' 
JOIN reportmsg AS R 
    ON n.source_id = r.msgid 
WHERE uid =: uid 
ORDER BY notificationid DESC 
LIMIT 20 

Sie können die Reihenfolge der Schalter schließt, können Sie B.STATUS = 'active' in der Join-Zustand bewegen, aber alle Anfragen werden das gleiche Ergebnis zurück. (Nach der Bearbeitung ist es eine LEFT JOIN, natürlich ist das Ergebnis jetzt anders)

Und natürlich sollten Sie nicht * verwenden, besser nur die Spalten auflisten, die Sie tatsächlich benötigen.

+0

alone 'join' wählt keine Zeile aus, mit' LINKER JOIN 'für Kommentar und Reportmg und' INNER JOIN' für gearbeitete Blogs aber Bedingung 'wo STATUS = 'activive' gilt sowohl für' comment' Tabelle als auch 'reportmsg' Gibt es irgendeine Möglichkeit, diese Bedingung nur für Kommentartabellen anzuwenden? –

+0

@ bɪɡɪnə: Wäre einfacher gewesen, wenn du ein paar Beispieldaten hinzugefügt hättest :-) Wahrscheinlich musst du den 'STATUS = 'active'' in den Join verschieben, ich werde meine Antwort bearbeiten. – dnoeth

5

Wie Sie aus dem Bild unten sehen können, können Sie nur andere Tabellen, um Benachrichtigungen Tabelle fusionieren müssen mit LEFT JOIN wie folgt aus:

SELECT n.notificationid, n.uid, n.idblog, n.source_id, 
     b.blogs_id, b.status, 
     c.id, 
     r.msgid 
     -- ... and the other columns you want 
FROM notifications n 
LEFT JOIN blogs b ON b.blogs_id = n.idblog AND b.STATUS = "active" AND n.uid =: uid 
LEFT JOIN comment c ON c.id = n.source_id  
LEFT JOIN reportmsg r ON r.msgid = n.source_id 
ORDER BY n.notificationid DESC 
LIMIT 20; 


SQL JOINS

Hoffnung, das hilft. ..

+2

Kein Punkt in' LEFT JOIN blogs b 'Wenn du' WHERE b.STATUS = "active" '... hast, wird dies effektiv in einen' INNER JOIN' umgewandelt. – Arth

+0

@Arth Du bist richtig, ich habe meine Antwort aktualisiert und verschiebe Bedingungen in "* WHERE *" Klausel zu "*AUF*". Vielen Dank. –

+0

Prost, aber jetzt erhalten Sie alle Benachrichtigungen, Kommentare und Reportmsgs und nur passende Blogs filtern .. ziemlich sicher, das ist nicht was OP will. – Arth

0

Es ist sehr unklar, was Sie hier sind .. während Ihre Tabelle Diagramm ist nützlich, Sie sollte tatsächlich einige Beispieldaten und ein erwartetes Ergebnis liefern, selbst wenn es nur ein paar Dummy-Zeilen für jede Tabelle ist.

Die Abfragen arbeiten Zeile für Zeile, beide INNER JOINs werden auf dieselbe Benachrichtigungszeile angewendet und nicht übereinstimmende Zeilen werden verworfen.

Jeder Filter gilt für beide JOIN und alle zurückgegebenen Zeilen müssen eine Übereinstimmung in BEIDE Kommentar und Reportmsg haben.

Vielleicht möchten Sie zwei LEFT JOIN, dass verschiedene Filter anwenden können und vielleicht aus den Tabellennamen zu erraten es könnte wie folgt aussehen:

SELECT * 
    FROM notifications n 
LEFT JOIN blogs b 
     ON n.blogId = b.blogs_id 
LEFT JOIN comment c 
     ON c.id = n.source_id 
     AND b.status = "Active" 
LEFT JOIN reportmsg rm 
     ON rm.msgid = n.source_id 
    WHERE n.uid =: uid 
     AND (c.id IS NOT NULL OR rm.msgid IS NOT NULL) 
ORDER BY n.notificationid DESC 
    LIMIT 20 

Sie sollten auch auf Ihre Namenskonvention arbeiten:

  • Benachrichtigungen, Kommentar -> Wählen Sie entweder Plural oder Singular Tabellennamen
  • notifications.notificationid, comment.id -> Wählen Sie den Tabellennamen zu ID hinzufügen
  • notificationid, source_id -> Strich oder keine Trennung Pick
  • idblog, notificationid -> Pick vorangestellt wird oder die ID-

Aktuell Sie haben ziemlich viel zu sehen jedes ID-Feld Anfügen jedes Mal, wenn Sie eine verwenden möchten.

1

Wenn Abfrage-Optimierer seine Arbeit macht, ist es egal, wo Sie Filter-Anweisung in INNER JOIN Fall, aber in der LEFT JOIN es hat Auswirkungen. Das Setzen einer Filterungsanweisung in LEFT JOIN Bedingungen bewirkt, dass zuerst die Tabelle gefiltert und danach die Filteranweisung in die WHERE-Klausel eingefügt wird, um die Ergebnisse von Join zu filtern. Wenn Sie also LEFT JOIN Ihre Abfrage muss verwenden möchten wie folgt aussehen:

SELECT nt.* 
    FROM notifications nt 
    LEFT JOIN Blogs bg on nt.blogs_id = bg.blogs_id and bg.STATUS = "active" 
    LEFT JOIN COMMENT cm ON cm.id = nt.source_id   
    LEFT JOIN reportmsg rm ON rm.msgid = nt.source_id 
    WHERE uid =: uid 
    ORDER BY nt.notificationid DESC 
    LIMIT 20;