Lists: | pgsql-de-allgemein |
---|
From: | Marc Hanisch <hanisch(at)ateam(dot)de> |
---|---|
To: | pgsql-de-allgemein(at)postgresql(dot)org |
Subject: | CASE und Aggregatfunktion |
Date: | 2009-03-26 09:18:01 |
Message-ID: | 49CB4849.5050900@ateam.de |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Lists: | pgsql-de-allgemein |
Hallo Liste,
ich nutze öfter eine Query in ähnlicher Art und Weise:
SELECT name,
CASE WHEN SUM(betrag) > 0
THEN SUM(betrag)
ELSE 0
END AS einnahmen,
CASE WHEN SUM(betrag) < 0
THEN SUM(betrag)
ELSE 0
END AS ausgaben
FROM table
GROUP BY name
Erreichen will ich damit, dass ein und das selbe Feld in Abhängigkeit
des Inhaltes also unter anderem Namen (einnahmen und ausgaben) ausgeben
wird.
Es erscheint mir aber umständlich, dass ich PostgreSQL für die Bedingung
(WHEN) und für die Anweisung (THEN) um die Summierung bemühen muss, was
ja wahrscheinlich doppelt Performance frisst... Gibt es da einen
eleganteren Weg? Schließlich wurde die Summe des Betrages ja bei der
ersten Bedingung bereits berechnet.
Viele Grüße,
Marc
From: | Thomas Markus <t(dot)markus(at)proventis(dot)net> |
---|---|
To: | marc(dot)hanisch(at)ateam(dot)de |
Cc: | pgsql-de-allgemein(at)postgresql(dot)org |
Subject: | Re: CASE und Aggregatfunktion |
Date: | 2009-03-26 10:05:43 |
Message-ID: | 49CB5377.90608@proventis.net |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Lists: | pgsql-de-allgemein |
Hi,
mach doch eher sowas wie:
SELECT name,
greatest(SUM(betrag),0) AS einnahmen,
least(SUM(betrag),0) AS ausgaben
FROM table
GROUP BY name
die abfrage scheint aber rein fachlich falsch zu sein da mindestens
einer der beiden summen 0 sein muss. Ich tippe mal es soll eher sowas
sein wie:
SELECT name,
sum(greatest(betrag,0)) AS einnahmen,
sum(least(betrag,0)) AS ausgaben
FROM table
GROUP BY 1
Gruss
Thomas
Marc Hanisch schrieb:
> Hallo Liste,
>
> ich nutze öfter eine Query in ähnlicher Art und Weise:
>
> SELECT name,
> CASE WHEN SUM(betrag) > 0
> THEN SUM(betrag)
> ELSE 0
> END AS einnahmen,
> CASE WHEN SUM(betrag) < 0
> THEN SUM(betrag)
> ELSE 0
> END AS ausgaben
> FROM table
> GROUP BY name
>
> Erreichen will ich damit, dass ein und das selbe Feld in Abhängigkeit
> des Inhaltes also unter anderem Namen (einnahmen und ausgaben) ausgeben
> wird.
> Es erscheint mir aber umständlich, dass ich PostgreSQL für die Bedingung
> (WHEN) und für die Anweisung (THEN) um die Summierung bemühen muss, was
> ja wahrscheinlich doppelt Performance frisst... Gibt es da einen
> eleganteren Weg? Schließlich wurde die Summe des Betrages ja bei der
> ersten Bedingung bereits berechnet.
>
> Viele Grüße,
> Marc
>
>
>
>
--
Thomas Markus
====================================================
proventis GmbH | Zimmerstr. 79-81 | D-10117 Berlin |
Tel +49 (0)30 2936399-22 | Fax -50 | t(dot)markus(at)proventis(dot)net
-----------------------------------------------------------------
Geschäftsführer: Norman Frischmuth | Sitz: Berlin
Handelsregister: AG Berlin-Charlottenburg, HR 82917
-----------------------------------------------------------------
Blue Ant-webbasiertes Projektmanagement - aktuelle Termine 2008:
http://www.proventis.net/website/live/blueant/veranstaltungen.html
====================================================
Attachment | Content-Type | Size |
---|---|---|
t_markus.vcf | text/x-vcard | 266 bytes |
From: | Marc Hanisch <hanisch(at)ateam(dot)de> |
---|---|
To: | Thomas Markus <t(dot)markus(at)proventis(dot)net> |
Cc: | pgsql-de-allgemein(at)postgresql(dot)org |
Subject: | Re: CASE und Aggregatfunktion |
Date: | 2009-03-26 10:11:46 |
Message-ID: | 49CB54E2.608@ateam.de |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Lists: | pgsql-de-allgemein |
--- Original-Nachricht ---
Absender: Thomas Markus
Datum: 26.03.2009 11:05 Uhr
> Hi,
>
> mach doch eher sowas wie:
>
> SELECT name,
> greatest(SUM(betrag),0) AS einnahmen,
> least(SUM(betrag),0) AS ausgaben
> FROM table
> GROUP BY name
Hallo Thomas,
danke, es sollte nur ein etwas konstruiertes Beispiel sein (was im
übrigen so auch schon funktionierend im Einsatz ist). Es ging mehr eher
darum, ob ich einen Wert, den ich im CASE WHEN Ausdruck ermittle und
anschließend ausgeben möchte, nochmal ermitteln muss oder ob es, um
Performance zu sparen, eine elegantere Art und Weise gibt, ein CASE zu
formulieren. Anstelle der Aggregatfunktion hätte ich als Beispiel auch
eine Subquery einfügen können, auch hier müsste die Subquery zweimal
ausgeführt werden... Hoffe ich hab mich verständlich ausgedrückt ;-)
Viele Grüße,
Marc
From: | Andreas Kretschmer <akretschmer(at)spamfence(dot)net> |
---|---|
To: | pgsql-de-allgemein(at)postgresql(dot)org |
Subject: | Re: CASE und Aggregatfunktion |
Date: | 2009-03-26 10:29:45 |
Message-ID: | 20090326102945.GA10641@tux |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Lists: | pgsql-de-allgemein |
Marc Hanisch <hanisch(at)ateam(dot)de> wrote:
> Hallo Liste,
>
> ich nutze öfter eine Query in ähnlicher Art und Weise:
>
> SELECT name,
> CASE WHEN SUM(betrag) > 0
> THEN SUM(betrag)
> ELSE 0
> END AS einnahmen,
> CASE WHEN SUM(betrag) < 0
> THEN SUM(betrag)
> ELSE 0
> END AS ausgaben
> FROM table
> GROUP BY name
Bist Du Dir sicher, damit das zu erreichen, was Du willst?
Ich denke, Du willst eher
sum(
case when betrag > 0 then betrag else 0 end) as einnahmen,
> Es erscheint mir aber umständlich, dass ich PostgreSQL für die Bedingung
> (WHEN) und für die Anweisung (THEN) um die Summierung bemühen muss, was
> ja wahrscheinlich doppelt Performance frisst... Gibt es da einen
> eleganteren Weg? Schließlich wurde die Summe des Betrages ja bei der
> ersten Bedingung bereits berechnet.
Mir erscheint es unlogisch, was Du machst:
test=*# select * from summen;
i | s
---+------
1 | 10
2 | 20
3 | -5
4 | -100
(4 Zeilen)
Zeit: 0,218 ms
test=*# select case when sum(s) > 0 then sum(s) end as einnahmen, case when sum(s) < 0 then sum(s) end as ausgaben from summen;
einnahmen | ausgaben
-----------+----------
| -75
(1 Zeile)
Zeit: 0,274 ms
test=*# select sum(case when s > 0 then s else 0 end) as einnahmen, sum(case when s < 0 then s else 0 end) as ausgaben from summen;
einnahmen | ausgaben
-----------+----------
30 | -105
(1 Zeile)
Welche Variante willst Du?
Andreas
--
Really, I'm not out to destroy Microsoft. That will just be a completely
unintentional side effect. (Linus Torvalds)
"If I was god, I would recompile penguin with --enable-fly." (unknown)
Kaufbach, Saxony, Germany, Europe. N 51.05082°, E 13.56889°
From: | Marc Hanisch <marc(dot)hanisch(at)ateam(dot)de> |
---|---|
To: | Andreas Kretschmer <akretschmer(at)spamfence(dot)net> |
Cc: | pgsql-de-allgemein(at)postgresql(dot)org |
Subject: | Re: CASE und Aggregatfunktion |
Date: | 2009-03-26 10:54:41 |
Message-ID: | 49CB5EF1.9030409@ateam.de |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Lists: | Postg토토 베이SQL : Postg토토 |
--- Original-Nachricht ---
Absender: Andreas Kretschmer
Datum: 26.03.2009 11:29 Uhr
>
>
> Mir erscheint es unlogisch, was Du machst:
>
> test=*# select * from summen;
> i | s
> ---+------
> 1 | 10
> 2 | 20
> 3 | -5
> 4 | -100
> (4 Zeilen)
>
> Zeit: 0,218 ms
> test=*# select case when sum(s) > 0 then sum(s) end as einnahmen, case when sum(s) < 0 then sum(s) end as ausgaben from summen;
> einnahmen | ausgaben
> -----------+----------
> | -75
> (1 Zeile)
>
> Zeit: 0,274 ms
> test=*# select sum(case when s > 0 then s else 0 end) as einnahmen, sum(case when s < 0 then s else 0 end) as ausgaben from summen;
> einnahmen | ausgaben
> -----------+----------
> 30 | -105
> (1 Zeile)
>
>
> Welche Variante willst Du?
>
>
Hallo Andreas,
genau die erste Variante will ich! Vielleicht hab ich mein Beispiel
schlecht gewählt, mir ging es inhaltlich darum zu sehen, dass ich, wenn
ich z.B. eine Kasse verwalte, ich am Monatsende im Minus bin (also -75)
oder halt im Plus. War aber nur ein frei gewähltes Beispiel.
Inhaltlich geht es mir darum, dass der Part
sum(s)
nach dem WHEN angegeben wird, und wenn der Inhalt meinen Erwartungen
entspricht, ich ihn ja nochmal von Postgres berechnen lassen muss...
Toll wäre so was in der "Art" wie:
when a = sum(s) > 0 then a else 0
Mir ist schon klar, dass man Variablen nur mit einer benutzerdefinierten
Funktion und PLPSQL erreichen kann, aber ich hoffe es verdeutlicht, was
ich meine.
Viele Grüße und danke für eure Nerven ;-)
Marc
From: | Marc Hanisch <hanisch(at)ateam(dot)de> |
---|---|
To: | pgsql-de-allgemein(at)postgresql(dot)org |
Subject: | Re: CASE und Aggregatfunktion |
Date: | 2009-03-26 10:56:05 |
Message-ID: | 49CB5F45.8010408@ateam.de |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Lists: | pgsql-de-allgemein |
--- Original-Nachricht ---
Absender: Andreas Kretschmer
Datum: 26.03.2009 11:29 Uhr
>
>
> Mir erscheint es unlogisch, was Du machst:
>
> test=*# select * from summen;
> i | s
> ---+------
> 1 | 10
> 2 | 20
> 3 | -5
> 4 | -100
> (4 Zeilen)
>
> Zeit: 0,218 ms
> test=*# select case when sum(s) > 0 then sum(s) end as einnahmen, case when sum(s) < 0 then sum(s) end as ausgaben from summen;
> einnahmen | ausgaben
> -----------+----------
> | -75
> (1 Zeile)
>
> Zeit: 0,274 ms
> test=*# select sum(case when s > 0 then s else 0 end) as einnahmen, sum(case when s < 0 then s else 0 end) as ausgaben from summen;
> einnahmen | ausgaben
> -----------+----------
> 30 | -105
> (1 Zeile)
>
>
> Welche Variante willst Du?
>
>
Hallo Andreas,
genau die erste Variante will ich! Vielleicht hab ich mein Beispiel
schlecht gewählt, mir ging es inhaltlich darum zu sehen, dass ich, wenn
ich z.B. eine Kasse verwalte, ich am Monatsende im Minus bin (also -75)
oder halt im Plus. War aber nur ein frei gewähltes Beispiel.
Inhaltlich geht es mir darum, dass der Part
sum(s)
nach dem WHEN angegeben wird, und wenn der Inhalt meinen Erwartungen
entspricht, ich ihn ja nochmal von Postgres berechnen lassen muss...
Toll wäre so was in der "Art" wie:
when a = sum(s) > 0 then a else 0
Mir ist schon klar, dass man Variablen nur mit einer benutzerdefinierten
Funktion und PLPSQL erreichen kann, aber ich hoffe es verdeutlicht, was
ich meine.
Viele Grüße und danke für eure Nerven ;-)
Marc
From: | Andreas Kretschmer <akretschmer(at)spamfence(dot)net> |
---|---|
To: | pgsql-de-allgemein(at)postgresql(dot)org |
Subject: | Re: CASE und Aggregatfunktion |
Date: | 2009-03-26 11:52:52 |
Message-ID: | 20090326115252.GA11603@tux |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Lists: | pgsql-de-allgemein |
Marc Hanisch <hanisch(at)ateam(dot)de> wrote:
> Hallo Liste,
>
> ich nutze öfter eine Query in ähnlicher Art und Weise:
>
> SELECT name,
> CASE WHEN SUM(betrag) > 0
> THEN SUM(betrag)
> ELSE 0
> END AS einnahmen,
> CASE WHEN SUM(betrag) < 0
> THEN SUM(betrag)
> ELSE 0
> END AS ausgaben
> FROM table
> GROUP BY name
>
> Erreichen will ich damit, dass ein und das selbe Feld in Abhängigkeit
> des Inhaltes also unter anderem Namen (einnahmen und ausgaben) ausgeben
> wird.
> Es erscheint mir aber umständlich, dass ich PostgreSQL für die Bedingung
> (WHEN) und für die Anweisung (THEN) um die Summierung bemühen muss, was
> ja wahrscheinlich doppelt Performance frisst... Gibt es da einen
> eleganteren Weg? Schließlich wurde die Summe des Betrages ja bei der
> ersten Bedingung bereits berechnet.
Okay, ich kann Dich beruhigen.
Ich erzeuge mir mal eine saudumme Aggregatfunktion, die eigentlich nix
weiter macht, als 1 zu liefern. Saudumm also. Nebenbei plappert sie aber
auch noch rum, immer wenn sie aufgrufen wird. Nicht so dumm für uns,
weil man dann sieht, wie oft sie aufgerufen wird:
test=# select * from summen;
i | s
---+------
1 | 10
2 | 20
3 | -5
4 | -100
(4 Zeilen)
Zeit: 0,151 ms
test=*# create or replace function agg_test(int, int) returns int as $$begin raise notice 'bin hier %',$2; return 1; end; $$language plpgsql immutable strict;
CREATE FUNCTION
Zeit: 0,695 ms
test=*# create aggregate agg_test(basetype=int, sfunc=agg_test, stype=int,initcond=1);
CREATE AGGREGATE
Zeit: 0,507 ms
test=*# select case when agg_test(s) > 0 then agg_test(s) end as einnahmen, case when agg_test(s) < 0 then agg_test(s) end as ausgaben from summen;
NOTICE: bin hier 10
NOTICE: bin hier 20
NOTICE: bin hier -5
NOTICE: bin hier -100
einnahmen | ausgaben
-----------+----------
1 |
(1 Zeile)
Wie man sieht, wird sie nur 1 mal pro Zeile aufgerufen. PG ist als
schlau genug, das zu optimieren.
Andreas
--
Really, I'm not out to destroy Microsoft. That will just be a completely
unintentional side effect. (Linus Torvalds)
"If I was god, I would recompile penguin with --enable-fly." (unknown)
Kaufbach, Saxony, Germany, Europe. N 51.05082°, E 13.56889°
From: | Marc Hanisch <hanisch(at)ateam(dot)de> |
---|---|
To: | Andreas Kretschmer <akretschmer(at)spamfence(dot)net> |
Cc: | pgsql-de-allgemein(at)postgresql(dot)org |
Subject: | Re: CASE und Aggregatfunktion |
Date: | 2009-03-26 12:04:40 |
Message-ID: | 49CB6F58.60506@ateam.de |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Lists: | Postg범퍼카 토토SQL : Postg범퍼카 |
--- Original-Nachricht ---
Absender: Andreas Kretschmer
Datum: 26.03.2009 12:52 Uhr
> Okay, ich kann Dich beruhigen.
>
> Ich erzeuge mir mal eine saudumme Aggregatfunktion, die eigentlich nix
> weiter macht, als 1 zu liefern. Saudumm also. Nebenbei plappert sie aber
> auch noch rum, immer wenn sie aufgrufen wird. Nicht so dumm für uns,
> weil man dann sieht, wie oft sie aufgerufen wird:
>
> test=# select * from summen;
> i | s
> ---+------
> 1 | 10
> 2 | 20
> 3 | -5
> 4 | -100
> (4 Zeilen)
>
> Zeit: 0,151 ms
> test=*# create or replace function agg_test(int, int) returns int as $$begin raise notice 'bin hier %',$2; return 1; end; $$language plpgsql immutable strict;
> CREATE FUNCTION
> Zeit: 0,695 ms
> test=*# create aggregate agg_test(basetype=int, sfunc=agg_test, stype=int,initcond=1);
> CREATE AGGREGATE
> Zeit: 0,507 ms
> test=*# select case when agg_test(s) > 0 then agg_test(s) end as einnahmen, case when agg_test(s) < 0 then agg_test(s) end as ausgaben from summen;
> NOTICE: bin hier 10
> NOTICE: bin hier 20
> NOTICE: bin hier -5
> NOTICE: bin hier -100
> einnahmen | ausgaben
> -----------+----------
> 1 |
> (1 Zeile)
>
>
> Wie man sieht, wird sie nur 1 mal pro Zeile aufgerufen. PG ist als
> schlau genug, das zu optimieren.
>
>
Hallo Andreas,
vielen Dank! Ich bin beeindruckt :-)
Jetzt bin ich beruhigt, da meine Query vielleicht blöd aussieht,
Postgres aber schlau genug dafür ist...
Viele Grüße,
Marc
From: | "Albe Laurenz" <laurenz(dot)albe(at)wien(dot)gv(dot)at> |
---|---|
To: | <marc(dot)hanisch(at)ateam(dot)de>, <pgsql-de-allgemein(at)postgresql(dot)org> |
Subject: | Re: CASE und Aggregatfunktion |
Date: | 2009-03-26 13:00:47 |
Message-ID: | D960CB61B694CF459DCFB4B0128514C202FF650D@exadv11.host.magwien.gv.at |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Lists: | pgsql-de-allgemein |
Marc Hanisch wrote:
> ich nutze öfter eine Query in ähnlicher Art und Weise:
>
> SELECT name,
> CASE WHEN SUM(betrag) > 0
> THEN SUM(betrag)
> ELSE 0
> END AS einnahmen,
> CASE WHEN SUM(betrag) < 0
> THEN SUM(betrag)
> ELSE 0
> END AS ausgaben
> FROM table
> GROUP BY name
>
> Erreichen will ich damit, dass ein und das selbe Feld in Abhängigkeit
> des Inhaltes also unter anderem Namen (einnahmen und ausgaben) ausgeben
> wird.
> Es erscheint mir aber umständlich, dass ich PostgreSQL für die Bedingung
> (WHEN) und für die Anweisung (THEN) um die Summierung bemühen muss, was
> ja wahrscheinlich doppelt Performance frisst... Gibt es da einen
> eleganteren Weg? Schließlich wurde die Summe des Betrages ja bei der
> ersten Bedingung bereits berechnet.
Ich muß zuerst einmal sagen, ich bin nicht sicher, ob PostgreSQL in diesem
Fall die Summe wirklich mehrmals berechnet - da kann vielleicht wer
Berufenerer Auskunft geben.
Ich hätte die Abfrage so formuliert:
SELECT name,
CASE WHEN sum_betrag) > 0
THEN sum_betrag)
ELSE 0
END AS einnahmen,
CASE WHEN sum_betrag) < 0
THEN sum_betrag)
ELSE 0
END AS ausgaben
FROM (SELECT name, sum(betrag) AS sum_betrag
FROM table
GROUP BY name) dummy;
Liebe Grüße,
Laurenz Albe