Frage

Ich habe eine Abfrage wie folgt:

SELECT t1.id,
    (SELECT COUNT(t2.id)
     FROM t2
     WHERE t2.id = t1.id
          ) as num_things
FROM t1
WHERE num_things = 5;

Das Ziel ist es, die ID aller Elemente zu erhalten, die 5-mal in der anderen Tabelle erscheinen. Allerdings habe ich diesen Fehler:

ERROR: column "num_things" does not exist
SQL state: 42703

Ich mache wahrscheinlich etwas albern hier, wie ich auf Datenbanken etwas neu bin. Gibt es eine Möglichkeit, diese Abfrage zu beheben, damit ich num_things zugreifen kann? Oder, wenn nicht, gibt es eine andere Möglichkeit, dieses Ergebnis zu erreichen?

War es hilfreich?

Lösung

Ich glaube, Sie nur Ihre Abfrage wie so umschreiben könnte:

SELECT t1.id
FROM t1
WHERE (SELECT COUNT(t2.id)
     FROM t2
     WHERE t2.id = t1.id
          ) = 5;

Andere Tipps

Einige wichtige Punkte über SQL verwenden:

  • Sie können nicht Spalte Aliase in der WHERE-Klausel verwenden, aber Sie können in der HAVING-Klausel. Das ist die Ursache für den Fehler Sie.
  • Sie können besser Ihre Zählung tun mit einem JOIN und GROUP BY als durch korrelierte Unterabfragen verwenden. Es wird viel schneller sein.
  • Verwenden Sie die HAVING-Klausel Gruppen zu filtern.

Hier ist die Art, wie ich diese Abfrage schreiben würde:

SELECT t1.id, COUNT(t2.id) AS num_things
FROM t1 JOIN t2 USING (id)
GROUP BY t1.id
HAVING num_things = 5;

Ich weiß, diese Abfrage die JOIN mit t1 überspringen kann, wie in Charles Bretana Lösung. Aber ich nehme an, Sie könnten die Abfrage einige andere Spalten von t1 aufgenommen werden sollen.


Re: die Frage im Kommentar:

Der Unterschied besteht darin, dass die WHERE Klausel auf Zeilen ausgewertet wird, bevor GROUP BY Gruppen zu einer einzelnen Zeile pro Gruppe reduziert. Die HAVING Klausel wird ausgewertet nach Gruppen gebildet werden. So kann man zum Beispiel nicht, ändern Sie die COUNT() einer Gruppe von HAVING verwendet wird; Sie können nur die Gruppe ausschließen selbst.

SELECT t1.id, COUNT(t2.id) as num
FROM t1 JOIN t2 USING (id)
WHERE t2.attribute = <value>
GROUP BY t1.id
HAVING num > 5;

In der obigen Abfrage, WHERE Filter für Zeilen eine Bedingung erfüllen, und HAVING Filter für Gruppen, die mindestens fünf Anzahl haben.

Der Punkt, den die meisten Menschen Verwirrung verursacht, ist, wenn sie nicht über eine GROUP BY Klausel haben, so dass es scheint wie HAVING und WHERE sind austauschbar.

WHERE wird, bevor Ausdrücke in der Auswahlliste ausgewertet. Dies kann nicht offensichtlich, da SQL-Syntax zuerst die Auswahlliste setzt. So können Sie eine Menge teuerer Berechnung sparen durch WHERE mit Zeilen zu beschränken.

SELECT <expensive expressions>
FROM t1
HAVING primaryKey = 1234;

Wenn Sie eine Abfrage wie die oben verwenden, die Ausdrücke in der Auswahlliste berechnet für jede Zeile , nur die meisten Ergebnisse zu verwerfen, weil der HAVING Zustand. Jedoch unterhalb der Abfrage berechnet den Ausdruck nur für die einreihige Anpassen der WHERE Zustand.

SELECT <expensive expressions>
FROM t1
WHERE primaryKey = 1234;

So zu rekapitulieren, werden Abfragen, die von dem Datenbank-Engine laufen nach Reihe von Schritten:

  1. Erzeugen von Zeilen aus der Tabelle (n) festgelegt, einschließlich der Zeilen, die von JOIN hergestellt.
  2. WHERE Bedingungen gegen den Satz von Zeilen auswerten, Zeilen herausgefiltert werden, die nicht übereinstimmen.
  3. Compute Ausdrücke in Auswahlliste für jeden in der Menge von Zeilen.
  4. Spalte Aliase Nehmen (beachten Sie, das ein separater Schritt ist, was bedeutet, dass Sie keine Aliase in Ausdrücke in der Auswahlliste verwenden können).
  5. Condense Gruppen zu einer einzelnen Zeile pro Gruppe nach GROUP BY Klausel.
  6. Ausrechnen HAVING Bedingungen gegen Gruppen, Gruppen Ausfiltern, die nicht übereinstimmen.
  7. Ergebnis sortiert nach ORDER BY Klausel.

Alle anderen Vorschläge funktionieren würde, aber Ihre grundlegende Frage zu beantworten, wäre es ausreichend, schreiben

  SELECT id  From T2
  Group By Id
  Having Count(*) = 5

Ich mag, dass in PostgreSQL erwähnen, dass es keine Möglichkeit gibt, in having-Klausel aliased Spalte zu verwenden.

d.

SELECT usr_id AS my_id FROM Benutzer MIT my_id = 1

wird nicht funktionieren.

Ein weiteres Beispiel, das nicht zur Arbeit gehen wird:

SELECT su.usr_id AS my_id, COUNT (*) FROM AS val sys_user AS su GROUP BY su.usr_id HAVING val> = 1

Es wird der gleiche Fehler sein. Val Spalte ist nicht bekannt,

Im highliting weil Bill Karwin schrieb etwas nicht wirklich wahr für Postgres:

„Sie können nicht Spalte Aliase in der WHERE-Klausel verwenden, aber Sie können in der HAVING-Klausel. Das ist die Ursache für den Fehler, den Sie bekommen.“

try this

SELECT t1.id,
    (SELECT COUNT(t2.id) as myCount
     FROM t2
     WHERE t2.id = t1.id and myCount=5
          ) as num_things
FROM t1
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top