Fehler im SELECT: Operator does not exist: bigint+boolean

Wenn ich folgendes SQL-Statement versuche aufzurufen:

SELECT     
round((n.rgt-n.lft-1)/2,0) AS childs,
count(*)+(n.lft>1) AS levels,
((min(p.rgt)-n.rgt-(n.lft>1))/2) > 0 AS lowers,
(( (n.lft-max(p.lft)>1) )) AS uppers
FROM t_chapter n, 
t_chapter p WHERE p.docuid=5 
AND n.lft BETWEEN p.lft AND p.rgt
AND (p.root = n.root)
AND (p.id != n.id OR n.lft = 1)
GROUP BY n.root,n.id
ORDER BY n.root,n.lft

Liefert PostgreSQL folgende Fehlermeldung zurück:

ERROR:  operator does not exist: bigint + boolean
HINT:  No operator matches the given name and argument type(s). You may need to add explicit type casts.

Weiß jemand was das bedeutet? Wo steckt der Fehler? upper und lower sind scheinbar Funktionen in PGSQL, deshalb hab ich sie geändert. Noch jemand eine Idee? round, count, min und max sollten eigentlich existieren …

THX,
Gruß,
Leeloo

Ok, das ist das Problem:

count(*)+(n.lft>1)

Ich kann keinen Bigint- mit einem Boolean-Wert verschmelzen o.ä… Das ist doch gemein. Kann man das irgendwie anders lösen?

Gruß,
Leeloo5E

Hi Leeloo,

ich verstehe nicht ganz, was du denn eigentlich machen willst? Soll das ein Counter werden, der immer wenn

(n.lft>1)

gilt, erhöht oder erniedrigt werden soll? Oder soll ein bestimmter Wert zurückgegeben werden?

[Edit]: Wenn du damit nur die Ausgabe von levels um 0 oder 1 erhöhen (Zeile 3 deiner Query) bzw. in Zeile 4 um 0 oder 1 erniedrigen willst, kannst du den Boole’schen Rückgabewert von (n.lft>1) auf int4 _cast_en (Infos zum Casten: Type Conversion)

SELECT     
  round((n.rgt-n.lft-1)/2,0) AS childs,
   count(*)+(n.lft>1)::int4 AS levels,
   ((min(p.rgt)-n.rgt-(n.lft>1)::int4)/2) > 0 AS lowers,
   (( (n.lft-max(p.lft)>1) )) AS uppers
FROM t_chapter n, 
     t_chapter p 
WHERE p.docuid=5 
  AND n.lft BETWEEN p.lft AND p.rgt
  AND (p.root = n.root)
  AND (p.id != n.id OR n.lft = 1)
GROUP BY n.root,n.id
ORDER BY n.root,n.lft

Nach der Doku ist der Datentyp boolean so implementiert, dass er auch in Zahlen darstellbar ist, wobei falsch/false 0 entspricht und wahr/true 1. Umgekehrt wird beim andersherum_cast_en 0 als falsch und jede andere Zahl als wahr interpretiert.

CU
Fröstel

Hi Fröstel,

vielen Dank. Genau der Hinweis hat mir gefehlt. :slight_smile:

Die Links haben mich zwar nur mehr verwirrt, als das sie geholfen haben, aber mit dem PGHandbuch und dem Hinweis auf Type Conversion bzw. Typumwandlung bin ich dann auch auf CAST gekommen.

CAST ( ausdruck AS typ )
expression::type

Schade ist nur, dass ich dort keinen genauen Hinweis erhalte, wass denn als typ bzw. type verwendet werden kann.
Scheinbar kann man sich aber selbst CASTs und TYPEs erstellen … Interessant.

vielen Dank nochmal,
Grüße,
Leeloo5E

Hi Leeloo5e,

ich vermute mal, dass du dir keinen eigenen CAST bauen musst. Du könntest es aber. Als TYPEs kannst du wohl alle Datentypen, die PostgreSQL vorhält, verwenden, aber auch selbstdefinierte.

Bei der Lösung für dein Problem stößt du übrigens auf zwei verschiedene Arten des CASTs:

(n.lft>1)::int4

ist ein expliziter CAST. Könntest du auch als

CAST ((n.lft>1) AS int4)

schreiben. Nach dieser expliziten, sprich von dir hingeschriebenen und für den Parser damit zwingenden, Typumwandlung kann der implizite CAST

count(*)+(n.lft>1)::int4

, also die implizite (automatische) Umwandlung des erzeugten Datentyps int4 in bigint erfolgen. Davon merkt man nichts, aber einen Operator +, der int4 zu einem bigint addiert, gibt es hier nicht. Durch die Typumwandlung des int4 zu bigint kann aber der Operator + für zwei Argumente des Typs bigint angewandt werden.

CU
Fröstel