2017-03-02 3 views
3

ich so kommen ein Recht zu tun:Rechts ohne Kreuzung kommen und eine andere Bedingung

enter image description here

Ich möchte alle B ohne A OR Alle B mit nur A.type <> 0 (wenn sie eine einzige A.type haben = 0 ich sie nicht wollen)

Für jetzt habe ich dies:

SELECT B.* 
FROM A 
RIGHT JOIN B ON A.ticket = B.id 
WHERE A.id IS NULL 
    AND B.state NOT IN (3,4,10) 
    AND B.disable = 0 
+0

Ich entfernte die inkompatiblen Datenbank-Tags. Bitte markieren Sie nur die von Ihnen verwendete Datenbank. –

+0

Versuchen Sie, 'AND A.type <> 0 'zu Ihrem where hinzuzufügen – MohaMad

+0

Können Sie erklären, warum Sie hier richtig Join wollen? Es ist wie 'wählen Sie nur optionale Daten von optionalen Daten richtig Join Haupttabelle '... – jarlh

Antwort

1

Es gibt keinen Grund, RIGHT JOIN zu verwenden. Für die meisten Menschen ist es aus zwei Gründen einfach verwirrender als LEFT JOIN. Zuerst wird die FROM Klausel "von links nach rechts" gelesen. A LEFT JOIN behält alle Zeilen in der ersten Tabelle in der Klausel. Die RIGHT JOIN in der noch nicht gesehenen letzten Tabelle. Zweitens wird die FROM-Klausel von links nach rechts geparst, was einige subtile Probleme beim Kombinieren mehrerer äußerer Joins einführt.

Als nächstes sagen Sie ausdrücklich:

iB ausschließen möchten, die keine A.Type hat = 0

Dies entspricht:

i möchte B einschließen, die keine haben A.Type = 0

Dies ist nicht qu Ite einen äußeren Join. Ich denke, das ist näher an, was Sie wollen:

In Ihrem Fall:

SELECT B.* 
FROM B 
WHERE NOT EXISTS (SELECT 1 
        FROM A 
        WHERE A.ticket = B.id AND A.Type = 0 
       ) AND 
     B.state NOT IN (3, 4, 10) AND B.disable = 0; 
+0

Was du gesagt hast ist wahr, ich will B, die nicht A oder A.type = 0 haben. Bezüglich deiner Frage bekomme ich ein B mit A oder A.type = 0 und wenn ich A.Type = 0 zu A.Type <> 0 ändere, habe ich das gleiche Ergebnis wie meine erste Abfrage. Aber danke – Philigane

+0

Wenn Sie wollen 'B' ohne' A', dann ist die Bedingung auf 'A.Type' irrelevant. Es sollte keine passende Zeile geben. Wenn das das ist, was Sie wollen, dann entfernen Sie 'A.Type = 0' aus der Unterabfrage. –

+0

Ich möchte B ohne A ODER B, die nur A.Type <> 0 (wenn sie nur 1 A.Type = 0 haben, ich will sie nicht) @Gordon Linoff – Philigane

0

Sie B wollen, wo, wenn es einen Wert in A beschwingt ist nach B, dann ist es geben <> 0, so:

SELECT * FROM B 
WHERE B.id NOT IN (
    SELECT ticket FORM A 
    WHERE A.type = 0) 

nicht akzeptabel

Mai werden Sie soetwas wie diese wollen:

SELECT B.* FROM A 
RIGHT JOIN B 
ON A.ticket = B.id 
WHERE 
    A.type<>0 
-- (A.id is null OR A.type<>0) 
-- A.id IS NULL 
-- AND A.type <> 0 -- added for exclude a.type = 0 
AND B.state NOT IN (3,4,10) 
AND B.disable = 0 

Es bedeutet JOIN ing wo A.type nicht 0 und andere Bedingungen, die Sie für Ihre Abfrage mit einer

+0

Das tue nicht, was ich brauche (aber danke). B Tabelle = Thread-Tabelle, A Tabelle = Nachrichtentabelle. Ich muss wissen, ob ein Thread keine Nachrichten hat (also keinen Eintrag in Tabelle A) oder wenn er keine Textnachrichten hat (Typ = 0, andere Typen sind erlaubt) – Philigane

+0

Also '(A.id ist null ODER A.Typ <> 0) 'kann nützlich sein? @Philigane – MohaMad

+0

Nein, sollte es sein, wenn ich Logik bin, aber ich bekomme einige Threads mit Nachrichten (weil ihre ID nicht null ist) @MohaMad – Philigane

0

Sie haben das gewünschte Ergebnis geplant statt einer Unterabfrage auf diese Weise verbinden:

select B.id 
from A right join B on A.ticket = B.id 
where B.state not in (3, 4, 10) and B.disable = 0 
group by B.id 
having count(case when A.ticket is not null and A.type = 0 then 1 end) = 0; 

auf diese Weise sind Sie nur unter Berücksichtigung der Reihen B, die eithe r haben keine übereinstimmende Zeile in A oder haben einige, aber keine mit A.type = 0.


Falsche pre-edit Antwort

Ich würde gehen mit:

select B.* 
from A right join B on A.ticket = B.id 
where B.state not in (3, 4, 10) and B.disable = 0 and coalesce(A.type, 1) <> 0 

Auf diese Weise können nur berücksichtigt werden die Zeilen, die entweder nicht beitreten oder beitreten, aber don Habe keine A.type = 0.

Beachten Sie, dass je nach der von Ihnen verwendeten Datenbank die coalesce-Funktion möglicherweise durch eine gleichwertige ersetzt werden muss.

+0

Es tut nicht, was ich brauche, ich bekomme ein paar Threads mit Nachrichten (dasselbe Ergebnis als @MohaMad). Aber danke – Philigane

0

Verwenden von Unterabfragen, um die gleiche Abfrage zu erhalten und das RECHTE JOIN beizubehalten. Diese Methode kann auch schneller sein, wenn sie versucht, die minimale Menge an Datensätzen aus den Tabellen auf den beiden JOIN-Seiten zu verknüpfen.

SELECT B2.* 
FROM 
    (SELECT ticket, type FROM A WHERE type=0) A2 
RIGHT JOIN 
    (SELECT * FROM B WHERE B.state NOT IN (3,4,10) AND B.disable = 0) B2 
ON A2.ticket = B2.id WHERE A2.ticket IS NULL; 
+0

A = A2 und B = B2 (gleicher Tabellenname)? @Dan Getz – Philigane

+0

Unterabfrage Tabellen müssen Namen. A2! = A zum Beispiel hat es nur Zeilen mit 'type = 0'. Die A2 und B2 müssen vor ihnen "AS" haben, aber es ist optional IIRC –

+0

Ein kleiner Typ ('A2.id' anstelle von' A2.ticket' in 'WHERE') wurde behoben.Es funktioniert in einer simulierten Sandbox von MySQL –