2016-04-01 6 views
2

ich auf Frage arbeiteWird INTERSECT gegenüber Unterabfragen bevorzugt?

alle Schüler finden, die in der Tabelle Likes (als Student, der gerne mag oder ist) nicht angezeigt und ihre Namen und Typen zurück. Sortieren Sie nach der Note, dann nach dem Namen in jeder Klasse.

Ich schlug vor, die folgenden tun, alle Menschen dazu zu bringen, die nicht Likes und mit den Menschen, die ich kreuz, die nicht jedermann gefällt:

SELECT name, grade 
    FROM Highschooler h1 
LEFT JOIN Likes l1 
    ON (l1.ID1 = h1.ID) 
WHERE l1.ID1 IS NULL 
INTERSECT 
SELECT name, grade 
    FROM Highschooler h1 
LEFT JOIN Likes l1 
    ON (l1.ID2 = h1.ID) 
WHERE l1.ID2 IS NULL 
ORDER BY grade, name 

Eine alternative Möglichkeit, dies mit einem zu tun Unterabfrage (wie ich online gefunden habe)

select name, grade from Highschooler H1 
where H1.ID not in (select ID1 from Likes union select ID2 from Likes) 
order by grade, name; 

Welcher Weg wird bevorzugt? Ich denke, dass meine Methode besser lesbar ist. Wie Adrien sagte, sind beide akzeptable Wege, es zu tun, Ich denke, Ihr Weg ist lesbarer wegen der Großbuchstaben-Funktionen und bessere Einrückung und nicht wegen der Abfrage selbst.

+0

Ich würde sagen, beide sind akzeptabel. Der Unterschied könnte in den Leistungen liegen und dieser Aspekt hängt normalerweise von der gegebenen Anwendung ab. –

+1

Ich dachte, MySQL unterstützt keine Schnittmenge. – apokryfos

Antwort

0

Dies ist, wie ich es zum Beispiel so tun würde:

SELECT name, grade 
FROM Highschooler H1 
LEFT JOIN Likes AS L1 ON L1.ID1 = H1.ID OR L1.ID2 = H1.ID 
WHERE L1.ID1 IS NULL 
ORDER BY grade, name 

Dieser Fall eines Anti-Join genannt würde. Lesen Sie mehr über die hier

https://explainextended.com/2009/09/18/not-in-vs-not-exists-vs-left-join-is-null-mysql/

Hier ist eine weitere schöne Blog-Post über die andere Art des mit einigen Diagrammen verbindet sie begleiten: http://blog.jooq.org/2015/10/06/you-probably-dont-use-sql-intersect-or-except-often-enough/

unser Fall würde Left Anti Join

+0

Dies ist ein Anti-Join? –

+0

Ja, Sie schließen sich einer Tabelle an, aber Sie möchten tatsächlich alle Werte aus der ersten Tabelle, die mit nichts übereinstimmen. nur in Ihrem Fall sind wir auf 2 Werte statt 1 – Jester

+0

@Phil hinzugefügt einen anderen Link, es hat einige schöne Venn-Diagramme einschließlich unserer Fall – Jester

0

Nein sein, Ihre Abfrage ist nicht gut lesbar. Lies es in einfacher Sprache: 1. Mache eine große Liste aller Schüler und ihrer Vorlieben. 2. Wenn für einen Schüler kein Eintrag für "Gefällt mir" gefunden wird, behalten Sie den Schülerbericht trotzdem bei. 3. Entferne dann alle Datensätze, die Likes enthalten (also nur diejenigen Schüler behalten, die keine Likes haben). 4.-6. Mach dasselbe mit der anderen Person in der Likertabelle. 7. Schneiden Sie die beiden Ergebnismengen.

Die ursprüngliche Aufgabe war nur: Finde Schüler, die nicht in der Likes-Tabelle existieren.

select name, grade 
from highschooler 
where not exists 
(
    select * 
    from likes 
    where likes.id1 = highschooler.id 
    or likes.id2 = highschooler.id 
) 
order by grade, name; 

Halten Sie Ihre Anfragen so einfach wie möglich. SQL wird mehr oder weniger so gelesen, als würden Sie die Aufgabe auf Englisch schreiben. Es ist nicht immer möglich, eine Aufgabe in so einfacher Form zu formulieren, aber Sie können es immer versuchen :-)

Das Anti-Join-Muster, das Sie in Ihrer Intersect-Abfrage verwenden, ist ein Trick, um Schwächen in jungen DBMS zu überwinden, die dies nicht tun komme gut mit IN und EXISTS schon zurecht. Sie sollten Tricks nur dann anwenden, wenn es notwendig ist, und nicht, wenn Sie sich mit so einer einfachen Aufgabe wie der gegebenen beschäftigen.

Verwandte Themen