2010-07-07 17 views
8

Ich habe eine Reihe von Benutzern, von denen jeder viele Posts hat. Schema:SQL-Abfrage mindestens eines von etwas

Users: id 
Posts: user_id, rating 

Wie finde ich alle Benutzer, die über mindestens einen Pfosten mit einem Rating haben, sagen wir, 10?

Ich bin mir nicht sicher, ob ich dafür eine Unterabfrage verwenden sollte oder ob es einen einfacheren Weg gibt.

Danke!

Antwort

19

Um alle Benutzer mit mindestens einem Beitrag mit einer Bewertung über 10 zu finden, verwenden Sie:

SELECT u.* 
    FROM USERS u 
WHERE EXISTS(SELECT NULL 
       FROM POSTS p 
       WHERE p.user_id = u.id 
       AND p.rating > 10) 

VORHANDEN nicht über die SELECT-Anweisung nicht kümmern innerhalb es - Sie könnten NULL durch 1/0 ersetzen, was zu einem mathematischen Fehler beim Teilen durch Null führen sollte ... Aber es wird nicht, weil EXISTS nur die Filterung in der WHERE-Klausel betrifft.

Die Korrelation (die WHERE p.user_id = u.id) ist der Grund, warum dies als korrelierte Unterabfrage bezeichnet wird und nur Zeilen aus der USERS-Tabelle zurückgegeben werden, in denen die ID-Werte übereinstimmen, zusätzlich zum Bewertungsvergleich.

EXISTS ist auch schneller, abhängig von der Situation, weil es wahr zurückgibt, sobald die Kriterien erfüllt sind - Duplikate spielen keine Rolle.

+0

Können Sie mir das erklären. Die innere Abfrage erhält eine beliebige Anzahl von NULL-Zeilen. Dann EXISTS kocht es auf wahr oder falsch, so wird es nicht nur alle Benutzer oder keine? – ash

+1

@Jasie: EXISTS kümmert sich nicht um die SELECT-Anweisung darin - Sie könnten NULL durch 1/0 ersetzen, was zu einem mathematischen Fehler beim Teilen durch Null führen sollte ... Aber es wird nicht, weil EXISTS nur betroffen ist mit der Filterung in der WHERE-Klausel. Die Korrelation (die 'WHERE p.user_id = u.id') ist der Grund, warum dies als korrelierte Unterabfrage bezeichnet wird und nur Zeilen aus der USERS-Tabelle zurückgibt, in der die ID-Werte übereinstimmen, zusätzlich zum Bewertungsvergleich. –

+0

@Jasie: EXISTS ist auch schneller, abhängig von der Situation, weil es wahr zurückgibt, sobald die Kriterien erfüllt sind - Duplikate spielen keine Rolle. –

1

Verwenden Sie eine innere Verknüpfung:

SELECT * from users INNER JOIN posts p on users.id = p.user_id where p.rating > 10; 
+1

Das wird Duplikate zurückgeben, wenn Benutzer mehr als einen Beitrag mit einer Bewertung über 10 haben. Fügen Sie "DISTINCT" hinzu, oder sehen Sie meine Abfrage für eine Alternative. –

+0

Wenn Sie nur eine Liste von Benutzern haben möchten, verwenden Sie die oben genannten, aber ersetzen Sie * durch unterschiedliche Benutzer.id – Kendrick

2

können Sie die Tabellen kommen Sie mit dem entsprechenden Benutzer zu finden, und DISTINCT verwenden, so dass jeder Benutzer im Ergebnis höchstens einmal selbst einstellen, wenn sie mehrere Beiträge mit Bewertung> 10 haben:

select distinct u.id,u.username 
from users u inner join posts p on u.id = p.user_id 
where p.rating > 10 
0
SELECT max(p.rating), u.id 
    from users u 
INNER JOIN posts p on users.id = p.user_id 
where p.rating > 10 
group by u.id; 

Darüber hinaus wird Ihnen sagen, was ihre höchste Bewertung ist.

+0

Entschuldigung - neu formatiert, um das Scrollen zu stoppen. Leichter zu lesen, einfacher zu wählen. –

+0

Danke, sieht besser so aus. – Zak

0

Die richtige Antwort für Ihre Frage wie angegeben ist OMG Ponies 'Antwort, wo EXISTEN beschreibender und fast immer schneller ist. Aber "SELECT NULL" sieht wirklich hässlich und kontraintuitiv zu mir aus. Ich habe SELECT * oder SELECT 1 als Best Practice dafür gesehen.

Ein anderer Weg, falls wir sammeln Antworten:

SELECT u.id 
FROM users u 
    JOIN posts p on u.id = p.user_id 
WHERE p.rating > 10 
GROUP BY u.id 
HAVING COUNT(*) > 1 

Dies könnte nützlich sein, wenn es Sie testen auf nicht immer 1 ist.

1
select distinct id 
from users, posts 
where id = user_id and rating > 10 
Verwandte Themen