# Mysql] Count aus Select in Where verwenden



## Moritz123 (4. Mai 2010)

Hallo allerseits!

ich habe hier ein 1:n-Relation und folgende Abfrage:

```
SELECT s.*, (SELECT COUNT(*) FROM USER_SEARCHLISTS c WHERE c.searchlists_id = s.id) as ucount 
FROM SEARCHLIST s
WHERE 1
```
Diese würde ich gerne um eine WHERE-Bedingung erweitern, die mir alle Datensätze liefert, die keinen Eintrag in users_searchlists enthält.
Eine Erweiterung um 
	
	
	



```
WHERE ucount = 0
```
 mündet aber in einen Fehler:


> #1054 - Unknown column 'ucount' in 'where clause'



Gibt es eine Möglichkeit diese im WHERE abzufragen?

Vielen Dank!


----------



## gorefest (4. Mai 2010)

Versuch mal 


```
SELECT *  
    FROM SEARCHLIST s
 WHERE NOT EXISTS (SELECT 1 FROM USERS_SEARCHLISTS u WHERE u.searchlists_id  = s.id)
```


----------



## gorefest (4. Mai 2010)

```
SELECT s.*, a.nCount 
     FROM SEARCHLIST s,
    (SELECT COUNT(*) nCount FROM USER_SEARCHLISTS c,
SEARCHLIST b WHERE c.searchlists_id = b.id)  a
WHERE  a.nCount  = 0;
```

da fehlt eine verküpfung zwischen s und a. Du bildest da gerade das kartesische Produkt beider Relationen.

Grüße
gore


----------



## Xervos (4. Mai 2010)

Stimmt  

man man ohne Tabellen tu ich mir immer so schwer aber er hat eh deine lösung werde meine dann rausnehmen das verwirrt sonst nur


----------



## Moritz123 (4. Mai 2010)

Hallo!

vielen Dank für Eure Antworten.
Da sich zwischenzeitlich die Anforderungen etwas geändert haben, gibt es eine zweite Tabelle, die die Relation zwischen User und Searchlist angeben, weswegen ich euer SQL wie folgt modifiziert habe (ohne WHERE):

```
SELECT s.*, buyer.bCount,seller.sCount
FROM 
searchlists s,
(SELECT COUNT(*) AS bCount, bs.searchlists_id FROM buyer_searchlists bs, searchlists sl1 WHERE bs.searchlists_id = sl1.id) AS buyer,
(SELECT COUNT(*) AS sCount, ss.searchlists_id FROM seller_searchlists ss, searchlists sl2 WHERE ss.searchlists_id = sl2.id) AS seller
```

Ich erhalte allerdings folgende Fehlermeldung:


> #1048 - Column 'searchlists_id' cannot be null


Kann es sein, dass diese Meldung darauf zurückzuführen ist, das die Tabellen leer sind? Das wäre nicht optimal.


----------



## Xervos (4. Mai 2010)

Moritz123 hat gesagt.:


> ```
> SELECT s.*, buyer.bCount,seller.sCount
> FROM
> searchlists s,
> ...




Sollte das nicht heißen seller.cCount anstelle von seller.sCount


----------



## Moritz123 (4. Mai 2010)

Ja, sorry - der Beitrag war auch noch gar nicht fertig. :-( Die aktualisierte Version findet sich weiter oben.


----------



## gorefest (4. Mai 2010)

```
SELECT s.*, buyer.bCount,seller.sCount
FROM 
searchlists s,
(SELECT COUNT(*) AS bCount, bs.searchlists_id FROM buyer_searchlists bs, searchlists sl1 WHERE bs.searchlists_id = sl1.id) AS buyer,
(SELECT COUNT(*) AS cCount, ss.searchlists_id FROM seller_searchlists ss, searchlists sl2 WHERE ss.searchlists_id = sl2.id) AS seller
```

wenn du den COUNT nicht brauchst, kannst Du nach wie vor performant mit EXISTS arbeiten. Es geht doch um COUNT == 0, oder?


```
SELECT s.*, buyer.bCount,seller.sCount
FROM  searchlists s
WHERE NOT EXISTS (SELECT 1  FROM buyer_searchlists bs WHERE bs.searchlists_id = s.id)
AND NOT EXISTS (SELECT 1  FROM seller_searchlists ss WHERE ss.searchlists_id = s.id)
```

Wenn Du allerdings den COUNT anteil mit benötigst :


```
SELECT s.id, s.weiterefelder, b.count, ss.count
 FROM searchlist s
 LEFT JOIN search buyer_searchlists b ON bs.searchlists_id = s.id
 LEFT JOIN seller_searchlists ss  ON  ss.searchlists_id = s.id
GROUP BY s.id, s.weiterefelder
```


----------



## Moritz123 (4. Mai 2010)

Hallo und danke nochmal.
Wie kann ich bei der LEFT JOIN-Lösung dann aber die Zahlenwerte aus den einzelnen Relationstabellen ermitteln? Ein COUNT(b.*) schlägt fehl?

Letztlich brauche ich sowohl den Count als auch die Möglichkeit die Query mit WHERE zu ergänzen, falls ein entsprechender Filter (Applikationslogik) gesetzt wird.

Vielen lieben Dank!


----------



## gorefest (4. Mai 2010)

Ups, war eh fehlerhaft.

das hier sollte tun :


```
SELECT s.id, s.weiterefelder, count(b.searchlists_id), count(ss.searchlists_id)
 FROM searchlist s
 LEFT JOIN search buyer_searchlists b ON bs.searchlists_id = s.id
 LEFT JOIN seller_searchlists ss  ON  ss.searchlists_id = s.id
GROUP BY s.id, s.weiterefelder
```

Wenn es definitiv Daten in einer der Partnerdatenquellen gibt, kannst Du auch INNER JOIN statt LEFT JOIN nehmen. Das ist performanter.


----------



## Moritz123 (4. Mai 2010)

OK, das hab ich jetzt soweit. Wenn ich dich/euch richtig verstanden habe, kann ich jetzt aber nicht einfach hingehen und diese Query um ein WHERE erweitern, das mir beispw. alle Searchlists gibt, die keine Relation zu einem Seller/Buyer haben oder?


----------



## gorefest (4. Mai 2010)

JA :


```
SELECT s.id, s.weiterefelder, count(b.searchlists_id), count(ss.searchlists_id)
 FROM searchlist s
 LEFT JOIN search buyer_searchlists b ON bs.searchlists_id = s.id
 LEFT JOIN seller_searchlists ss  ON  ss.searchlists_id = s.id
GROUP BY s.id, s.weiterefelder
HAVING COUNT(b.searchlists_id) = 0
```

Nochmals, wenn der Count nicht mit in die Selektion muss, nimm EXISTS.


----------



## Moritz123 (4. Mai 2010)

Hallo !

vielen Dank - ich habe das jetzt mal so eingebaut und Testdaten eingefügt: Es gibt zwei Einträge in der "searchlists" mit jeweils drei Einträgen in der "seller_searchlists" bzw. "buyer_searchlists".
Ohne das "HAVING" liefert er mir für jeden Eintrag in der "searchlists" aber jeweils neun Einträge in den beiden anderen zurück, was mir schwer nach Kreuzprodukt aussieht.
Das angepasste SQL sieht nun wie folgt aus:

```
SELECT s.id, count(bs.searchlists_id), count(ss.searchlists_id)
 FROM searchlists s
 LEFT JOIN buyer_searchlists bs ON bs.searchlists_id = s.id
 LEFT JOIN seller_searchlists ss  ON ss.searchlists_id = s.id
GROUP BY s.id
```


----------



## Moritz123 (4. Mai 2010)

Ok, ich habs nun selbst hingefummelt:

```
SELECT s.id, count(bs.searchlists_id) as buyercount, ss.sellercount
 FROM searchlists s
 LEFT JOIN buyer_searchlists bs ON bs.searchlists_id = s.id
 INNER JOIN (
  SELECT s1.id, count(ss2.id) as sellercount FROM searchlists s1
  LEFT JOIN seller_searchlists ss2 ON ss2.searchlists_id = s1.id
  GROUP BY s1.id
 ) AS ss ON ss.id = s.id 
GROUP BY s.id
```

Anders scheint es mir nicht zu gehen.


----------

