Sql error 42803 error aggregate functions are not allowed in where

How to fi this error Err] ERROR: aggregate functions are not allowed in WHERE this my query select count(case daftar.daftar when 'sd' then 1 else null end) as sd, count(case daftar.daftar when...

How to fi this error

Err] ERROR: aggregate functions are not allowed in WHERE

this my query

select count(case daftar.daftar when 'sd' then 1 else null end) as sd,
 count(case daftar.daftar when 'smp' then 1 else null end) as smp,
 count(case daftar.daftar when 'sma' then 1 else null end) as sma
from daftar
join gelombang on  daftar.gel=gelombang.id
join ajaran on ajaran.id=gelombang.id_ajar
join tahun on tahun.id=ajaran.tahun
where daftar.status='terima' and daftar.pindahan='no' and tahun.id= max(tahun.id)

asked Dec 22, 2016 at 6:43

faza's user avatar

3

You can use «HAVING» to tackle this:

HAVING tahun.id= max(tahun.id)

select count(case daftar.daftar when 'sd' then 1 else null end) as sd,
 count(case daftar.daftar when 'smp' then 1 else null end) as smp,
 count(case daftar.daftar when 'sma' then 1 else null end) as sma
from daftar
join gelombang on  daftar.gel=gelombang.id
join ajaran on ajaran.id=gelombang.id_ajar
join tahun on tahun.id=ajaran.tahun
where daftar.status='terima' and daftar.pindahan='no' 
HAVING tahun.id= max(tahun.id)

answered Apr 13, 2017 at 16:09

allen's user avatar

allenallen

3565 silver badges8 bronze badges

One option is to use a subquery to calculate that max value:

select count(case daftar.daftar when 'sd' then 1 else null end) as sd,
       count(case daftar.daftar when 'smp' then 1 else null end) as smp,
       count(case daftar.daftar when 'sma' then 1 else null end) as sma
from daftar
inner join gelombang
    on daftar.gel = gelombang.id
inner join ajaran
    on ajaran.id = gelombang.id_ajar
inner join tahun
    on tahun.id = ajaran.tahun
where daftar.status = 'terima' and
      daftar.pindahan = 'no'   and
      tahun.id = (select max(id) from tahun)

answered Dec 22, 2016 at 6:47

Tim Biegeleisen's user avatar

Tim BiegeleisenTim Biegeleisen

490k25 gold badges267 silver badges344 bronze badges

Aggregates functions we use only in SELECT block. You can use inner select for this case:where daftar.status='terima' and daftar.pindahan='no' and tahun.id=(select max(id) from tahun)

answered Dec 22, 2016 at 6:51

Mr. Skip's user avatar

Mr. SkipMr. Skip

4074 silver badges10 bronze badges

2

use a subquery, group by or having clause

answered Dec 22, 2016 at 7:09

kimdasuncion12's user avatar

kimdasuncion12kimdasuncion12

3032 gold badges4 silver badges16 bronze badges

I want to insert a tuple in my leggeapprovata table, but this table takes the attributes from 4 other tables. One of these 4 tables is the votazione table, from which it takes 6 attributes. Two do not give me errors, but for the others 4 attributes, it gives me the same error, ie that you can not use the aggregation function max in the where clause.

To avoid that the selection gives me more lines, since in the vote there are more tuples with different dates, I want the tuple with the most recent date (MAX (votazione.data)), but it gives me the error I was talking about before:

ERROR: the aggregation functions are not allowed in GROUP BY LINE 17: 
... ect votazione.favorevoli from votazione group by (MAX(vota ... ^
********** Error **********
ERROR: aggregate functions are not allowed in GROUP BY SQL state: 42803

I also tried with where, case when, having, but I still receive an error message.

Insert/Select statement

Following is the statement I am trying to execute.

INSERT INTO leggeapprovata (titolo, 
     relatore,
     numerolegislatura,
     testo,
     votisi,
     votino,
     astenuti,
     datapromulgazione,
     promulgatada,
     numlegge,
     dataapprovazionecamera,
     dataapprovazionesenato) 
  SELECT ddl.titolo, 
     ddl.relatore,
     legislatura.numero,
     ddl.testo,
     (select votazione.favorevoli from votazione group by (MAX(votazione.data)) AND tipoassemblea='senato'),
     (select votazione.contrari  from votazione group by (MAX(votazione.data)) AND tipoassemblea='senato'),
     (select votazione.astenuti  from votazione group by (MAX(votazione.data)) AND tipoassemblea='senato'),
     promulgazione.data,
     promulgazione.presidente,
     (select votazione.codice  from votazione  group by (MAX(votazione.data)) AND tipoassemblea='senato'),
     (select MAX(votazione.data) from votazione,ddl where tipoassemblea='camera' and votazione.ddl=ddl.titolo),
     (select MAX(votazione.data) from votazione,ddl where tipoassemblea='senato' and votazione.ddl=ddl.titolo)
   FROM ddl, legislatura, votazione, promulgazione
   WHERE ddl.promulgato='si' and ddl.titolo=promulgazione.ddl and (promulgazione.data between legislatura.datainizio and legislatura.datafine);

Table Definition

CREATE TABLE public.leggeapprovata
(
  titolo character varying(1000) NOT NULL,
  numerolegislatura integer NOT NULL,
  testo text,
  votisi integer,
  votino integer,
  astenuti integer,
  datapromulgazione date,
  promulgatada character varying(100),
  relatore character varying(100)[] NOT NULL,
  dataapprovazionecamera date,
  dataapprovazionesenato date,
  numlegge character(10),
  CONSTRAINT leggeapprovatapkey PRIMARY KEY (titolo, numerolegislatura, relatore),
  CONSTRAINT leggeapprovatanumerolegislaturafkey FOREIGN KEY (numerolegislatura)
      REFERENCES public.legislatura (numero) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT leggeapprovatapromulgatadafkey FOREIGN KEY (promulgatada)
      REFERENCES public.presidentedellarepubblica (presidente) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT leggeapprovatatestofkey FOREIGN KEY (testo, relatore)
      REFERENCES public.ddl (testo, relatore) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT leggeapprovatatitolofkey FOREIGN KEY (titolo, datapromulgazione)
      REFERENCES public.promulgazione (ddl, data) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT leggeapprovatavotisifkey FOREIGN KEY (votisi, votino, astenuti, numlegge)
      REFERENCES public.votazione (favorevoli, contrari, astenuti, codice) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION,
  CONSTRAINT leggeapprovatatitolonumerolegislaturatestorelatorenukey UNIQUE (titolo, numerolegislatura, testo, relatore, numlegge)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE public.leggeapprovata
  OWNER TO postgres;
GRANT ALL ON TABLE public.leggeapprovata TO public;
GRANT ALL ON TABLE public.leggeapprovata TO postgres WITH GRANT OPTION;

Trigger Definitons

-- Trigger: inserimentoinleggeapprovata on public.leggeapprovata

-- DROP TRIGGER inserimentoinleggeapprovata ON public.leggeapprovata;

CREATE TRIGGER inserimentoinleggeapprovata
  BEFORE INSERT
  ON public.leggeapprovata
  FOR EACH ROW
  WHEN ((pg_trigger_depth() = 0))
  EXECUTE PROCEDURE public.inserimentoinleggeapprovata();
ALTER TABLE public.leggeapprovata DISABLE TRIGGER inserimentoinleggeapprovata;
COMMENT ON TRIGGER inserimentoinleggeapprovata ON public.leggeapprovata IS 'when (pg_trigger_depth()=)livello di annidamento corrente dei trigger PostgreSQL (0 se non viene chiamato, direttamente o indirettamente, da un trigger)';



CREATE TRIGGER inserimentoinleggeapprovata
  BEFORE INSERT
  ON public.leggeapprovata
  FOR EACH ROW
  WHEN ((pg_trigger_depth() = 0))
  EXECUTE PROCEDURE public.inserimentoinleggeapprovata();
COMMENT ON TRIGGER inserimentoinleggeapprovata ON public.leggeapprovata IS 'when (pg_trigger_depth()=)livello di annidamento corrente dei trigger PostgreSQL (0 se non viene chiamato, direttamente o indirettamente, da un trigger)';

Function Definitions

-- Function: public.inserimentoinleggeapprovata()

-- DROP FUNCTION public.inserimentoinleggeapprovata();

CREATE OR REPLACE FUNCTION public.inserimentoinleggeapprovata()
  RETURNS trigger AS
$BODY$
begin
if exists (select 1 from leggeapprovata
where leggeapprovata.titolo = NEW.titolo)
   THEN 
        RAISE EXCEPTION '% già ESISTENTE IN leggeapprovata', NEW.titolo;
   ELSE  RETURN new;
   end if;
end;

$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 1000;
ALTER FUNCTION public.inserimentoinleggeapprovata()
  OWNER TO postgres;
GRANT EXECUTE ON FUNCTION public.inserimentoinleggeapprovata() TO postgres;
GRANT EXECUTE ON FUNCTION public.inserimentoinleggeapprovata() TO public;

I would appreciate any feedback regarding the error message.


Votazione Table Data

This is the first image of the votazione table:

enter image description here

This is the second image of the votazione table:

enter image description here

Pavel Stehule’s blog

Some notes about PostgreSQL

Monday, August 25, 2008

Using cursors for generating cross tables

I am working on procedure support in PostgreSQL more than one year. Missing procedures is one disadvantage of PostgreSQL. Because procedures are not called from SELECT statement, then it couldn’t respect some rules like functions. Procedures are mainly used for explicit transaction controlling and for generating mutable results (like dynamic record set or stacked record set). Dynamic record set is interesting feature when we nothing know about result set’s columns. It’s typical for cross tables. Because PostgreSQL doesn’t support procedures, we cannot return dynamic (mutable number of columns) queries directly, but we can return dynamic cursor. This method of generating cross tables is inspired by Roland Bauman’s http://rpbouman.blogspot.com blog.
Cross table is based on query’s pattern:

for data:
I write function, that generate necessary SELECT statement and open dynamic cursor.
Because cursors should be used only in transaction, I have to use explicit transaction:
There is result:
A alternative for this solution is using a tablefuc extension:

posted by Pavel Stěhule @ 2:54 AM 15 Comments

15 Comments:

At least on Firefox, the SQL text in the page is truncated. May it be possible to fix the CSS or to wrap the text so it is readable ?

Thank you for your valuable work on postgreSQL

At August 26, 2008 at 4:07 AM , Pavel Stěhule said.

I reformated article. Wrong style 🙁

At February 18, 2009 at 12:15 PM , Anonymous said.

Your article was very helpful to me, thanks a lot 🙂
w

At July 7, 2009 at 4:11 PM , Gustavo Straube said.

Very good article! It’s just what I’ve looking for.

I have one question: probably I’ll use this technique in an application I’m developing and want to know about the impact in terms of performance with a large ammount of data. Is it fine?

At July 7, 2009 at 10:38 PM , Pavel Stěhule said.

what I know, this method is the best on SQL level. But on very large tables this query should run long time. PostgreSQL missing OLAP or ROLAP support. Try it and you will see. This solution is very simple, but if it will be too slow you can use some general OLAP sw — Mondrian, Pentaho

At February 12, 2010 at 4:45 AM , Anonymous said.

How about implementing a new keyword in Postgres, like EXECUTE PROCEDURE ‘function_name()’ which returns «SETOF RECORD», and which is equivalent to SELECT * FROM ‘function_name()’, but doesn’t give you an error?

At February 12, 2010 at 4:58 AM , Pavel Stěhule said.

This is in my ToDo (when I meet some sponsor). It is standardized: CREATE PROCEDURE and CALL statement.

At July 19, 2010 at 6:29 PM , irman said.

Brilliant article. it is simpler to do crosstab ;;)

At June 11, 2012 at 9:23 PM , Prof. Adriano Aguzzi, MD PhD DVM h.c. FRCP FRCPath said.

I am a molecular biologist and have minimal Postgres knowledge, so my question is very naive. I pasted your code into pgAdmin sql window, and everything works fine, your function is being created. But when I execute your procedure, PG says «3 rows discarded» and shows nothing. I am sure that this is because of my ignorance — can you tell me how to do it right? My goal is to create simple dynamic pivot queries like with Access.

At June 11, 2012 at 11:33 PM , Pavel Stěhule said.

To Adriano: you can test it in console? What are you doing exactly? This is pgAdmin message or PostgreSQL message?

At June 18, 2012 at 10:07 PM , Prof. Adriano Aguzzi, MD PhD DVM h.c. FRCP FRCPath said.

Dear Pawel
thank you for your help. When I paste the function into pgAdmin without wrapping it into the transaction, it works fine. Within the transaction block, it rejects the output. I will try to read more about transactions in order to understand this behavior.
I have a big question though. Could you write a very short (3-4 lines) documentation of the parameters of your function? What is the admissible parameter syntax, etc? A million thanks in advance.

At June 18, 2012 at 10:23 PM , Prof. Adriano Aguzzi, MD PhD DVM h.c. FRCP FRCPath said.

well, I tried the following:

SELECT do_cross_cursor( ‘varid’,
‘FROM loggingdb_ips_boolean As log’,
‘to_char(ipstimestamp, »mon DD HH24h»)’,
‘FROM loggingdb_ips_boolean As log’,
‘COUNT(*)::integer’);
FETCH ALL FROM result;

But it aborts with the following message:
ERROR: aggregate function calls cannot be nested
SQL state: 42803
Context: PL/pgSQL function «do_cross_cursor» line 19 at OPEN

Does this mean that one cannot use aggregate functions within this cursor?

At June 20, 2012 at 1:32 AM , Pavel Stěhule said.

To Adriano: You can use aggregate function with cursors — but you cannot nested aggregates — if you can understand code — it is based on dynamic SQL — then some query is dynamically created — and it use SUM as example. When you use COUNT(*), then it creates query with ..SUM( .. COUNT(*)) that is not valid. If you can use COUNT, then you have to modify source code. /parameters — it is column name and source, column name and source.

At August 1, 2012 at 1:01 AM , Peter said.

Hi Pavel Stěhule
its a beautiful code to create cross relation pivot table. i need to change all diagonal values to ‘N/A’. i have been trying to make some changes but could not succeeded. can you plz tell me how can i do this.

At August 1, 2012 at 1:31 AM , Unknown said.

hi there . your blog has helped me alot thank you very much . now i need some altretaion in this besause my requirmnts are slightly different . my scenario is i have three columns say
A(text) B(text) Value(text)
AA1 AA1 0
AA2 AA1 100
AA3 AA1 100
AA1 AA2 100
AA2 AA2 0
AA3 AA2 100
AA1 AA3 100
AA2 AA3 100
AA3 AA3 0

now i want a cross table that looks like
AA1 AA2 AA3
AA1 0 100 100
AA2 100 0 100
AA3 100 100 0

and then it should replace o with not applicable (N/A) so i am looking a cross table like

AA1 AA2 AA3
AA1 N/A 100 100
AA2 100 N/A 100
AA3 100 100 N/A

i have achieved the table with zeros but i am unable to place N/A value where row and column name is same i,e fro AA1 to AA1 or AA2 to AA2 . thans i will wait for your reply

Subscribe to Post Comments [Atom]

Name: Pavel Stěhule Location: Prague, Česká republika, Czechia

Источник

I have the following data:

table: identifier

objectid    type    name            value
9345783451  GUID    msisdn          bc3b2286379da25fd6ef3bac120827589c783
9345783451  UMID    umid            f701a99c-96c9-4d4a-8508-932eeeaca77c
9345783451  UMDID   umdid           2840f267-4bdd-4af4-8b36-72badbce1e11
9345783451  UMDID   umdid           bbe467f5-0fc4-4624-8b01-dd656767d3b2
9345783451  GUID    encrypted       ZPmBF2Spq8DBX0wl
9345783451  UMDID   umdid           a4c6b3cb-938f-4ae5-8246-f2612ffd946b
9345783451  UMDID   umdid           2a8e5f98-5a74-431e-bbaf-7c75fdeb991a
9345783451  UMDID   umdid           269a39b9-1122-4d08-9ca4-36f6c8e00e8e
9345783451  COOKIE  amcv            39852788960115122553605179944081330813
9345783451  UMDID   umdid           7715969f-63ab-4540-952c-73beafb46024
9345783451  GROUPID ban-sha2        1d98f855e9a4fbeba1937f774b6dbab2ca194b5
9345783451  COOKIE  token           21agqB6x_H8.1575825731298.aXHr4GoVupopE
9345783451  GUID    acn             12433792
9345783451  UMDID   umdid           f2cf7402-21d2-44ea-b432-66e997cfebbf
9345783451  GUID    targetId        1255625699
9345783451  UMDID   umdid           b8d55cdd-4a95-4e07-8eeb-f281a0961a6a
9345783451  UMDID   umdid           af890608-b512-4a96-9274-f39f388ff442
9345783451  UMDID   umdid           0c55ecb1-e24e-419d-97a1-48f6eba45fe0

Then i do the following query:

select objectid,
           count(objectid) filter ( where type = 'GUID' )                                                                     as guid_count,
           count(objectid) filter ( where type = 'GUID' and (name in
                                                             ('acn', 'encrypted', 'kdid', 'msisdn', 'targetId')) ) as cuid_count,
           count(objectid) filter ( where name = 'umdid' )                                                                    as umdid_count
    from identifier
    where objectid = '9345783451'
    group by objectid;

The result is correct:

objectid    guid_count cuid_count umdid_count
9345783451  4          3          10

Then i add two column, name and value:

select objectid,
               count(objectid) filter ( where type = 'GUID' )                                                                     as guid_count,
               count(objectid) filter ( where type = 'GUID' and (name in
                                                                 ('acn', 'encrypted', 'kdid', 'msisdn', 'targetId')) ) as cuid_count,
               count(objectid) filter ( where name = 'umdid' )                                                                    as umdid_count,
               case
                   when identifier.name = 'acn' then identifier.value::text
                   else '' end                                                                                                                          as acn
        from identifier
        where objectid = '9345783451'
        group by objectid, name, value;

That return:

objectid   guid_count cuid_count umdid_count acn
9345783451  0          0         1           "" 
9345783451  1          0         0           "" 
9345783451  0          0         1           "" 
9345783451  0          0         0           "" 
9345783451  0          0         1           "" 
9345783451  1          1         0           12433792 
9345783451  0          0         1           "" 
9345783451  0          0         1           "" 
9345783451  1          1         0           "" 
9345783451  0          0         0           "" 
9345783451  0          0         1           "" 
9345783451  0          0         1           "" 
9345783451  0          0         0           "" 
9345783451  0          0         1           "" 
9345783451  0          0         1           "" 
9345783451  0          0         0           "" 
9345783451  1          1         0           "" 
9345783451  0          0         1           ""

"" empty string

What i expect is:

objectid    guid_count cuid_count umdid_count acn
9345783451  4          3          10          12433792

If i add group by on guid_count, cuid_count, and umdid_count:

[42803] ERROR: aggregate functions are not allowed in GROUP BY Position: 26

How to overcome this problem? Could you help point me where my mistake is?

Thank you.

Advertisement

Answer

You should use an aggregate for the added column, e.g.:

select objectid,
    count(objectid) filter ( where type = 'GUID' ) as guid_count,
    count(objectid) filter ( 
        where type = 'GUID' 
        and (name in ('acn', 'encrypted', 'kdid', 'msisdn', 'targetId')) 
        ) as cuid_count,
    count(objectid) filter ( where name = 'umdid' ) as umdid_count,
    max(case
        when identifier.name = 'acn' then identifier.value::text
        else '' end) as acn
from identifier
where objectid = '9345783451'
group by objectid;

Понравилась статья? Поделить с друзьями:
  • Sql error 22023 error cannot extract elements from a scalar
  • Sql error 22008 error date time field value out of range
  • Sql error 22003 ошибка целое вне диапазона
  • Sql error 22001 sqlstate 22001
  • Sql error 212