1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815 |
- --
- -- AGGREGATES
- --
- -- avoid bit-exact output here because operations may not be bit-exact.
- SET extra_float_digits = 0;
- SELECT avg(four) AS avg_1 FROM onek;
- avg_1
- --------------------
- 1.5000000000000000
- (1 row)
- SELECT avg(a) AS avg_32 FROM aggtest WHERE a < 100;
- avg_32
- ---------------------
- 32.6666666666666667
- (1 row)
- -- In 7.1, avg(float4) is computed using float8 arithmetic.
- -- Round the result to 3 digits to avoid platform-specific results.
- SELECT avg(b)::numeric(10,3) AS avg_107_943 FROM aggtest;
- avg_107_943
- -------------
- 107.943
- (1 row)
- SELECT avg(gpa) AS avg_3_4 FROM ONLY student;
- avg_3_4
- ---------
- 3.4
- (1 row)
- SELECT sum(four) AS sum_1500 FROM onek;
- sum_1500
- ----------
- 1500
- (1 row)
- SELECT sum(a) AS sum_198 FROM aggtest;
- sum_198
- ---------
- 198
- (1 row)
- SELECT sum(b) AS avg_431_773 FROM aggtest;
- avg_431_773
- -------------
- 431.773
- (1 row)
- SELECT sum(gpa) AS avg_6_8 FROM ONLY student;
- avg_6_8
- ---------
- 6.8
- (1 row)
- SELECT max(four) AS max_3 FROM onek;
- max_3
- -------
- 3
- (1 row)
- SELECT max(a) AS max_100 FROM aggtest;
- max_100
- ---------
- 100
- (1 row)
- SELECT max(aggtest.b) AS max_324_78 FROM aggtest;
- max_324_78
- ------------
- 324.78
- (1 row)
- SELECT max(student.gpa) AS max_3_7 FROM student;
- max_3_7
- ---------
- 3.7
- (1 row)
- SELECT stddev_pop(b) FROM aggtest;
- stddev_pop
- -----------------
- 131.10703231895
- (1 row)
- SELECT stddev_samp(b) FROM aggtest;
- stddev_samp
- ------------------
- 151.389360803998
- (1 row)
- SELECT var_pop(b) FROM aggtest;
- var_pop
- ------------------
- 17189.0539234823
- (1 row)
- SELECT var_samp(b) FROM aggtest;
- var_samp
- ------------------
- 22918.7385646431
- (1 row)
- SELECT stddev_pop(b::numeric) FROM aggtest;
- stddev_pop
- ------------------
- 131.107032862199
- (1 row)
- SELECT stddev_samp(b::numeric) FROM aggtest;
- stddev_samp
- ------------------
- 151.389361431288
- (1 row)
- SELECT var_pop(b::numeric) FROM aggtest;
- var_pop
- --------------------
- 17189.054065929769
- (1 row)
- SELECT var_samp(b::numeric) FROM aggtest;
- var_samp
- --------------------
- 22918.738754573025
- (1 row)
- -- population variance is defined for a single tuple, sample variance
- -- is not
- SELECT var_pop(1.0::float8), var_samp(2.0::float8);
- var_pop | var_samp
- ---------+----------
- 0 |
- (1 row)
- SELECT stddev_pop(3.0::float8), stddev_samp(4.0::float8);
- stddev_pop | stddev_samp
- ------------+-------------
- 0 |
- (1 row)
- SELECT var_pop('inf'::float8), var_samp('inf'::float8);
- var_pop | var_samp
- ---------+----------
- NaN |
- (1 row)
- SELECT stddev_pop('inf'::float8), stddev_samp('inf'::float8);
- stddev_pop | stddev_samp
- ------------+-------------
- NaN |
- (1 row)
- SELECT var_pop('nan'::float8), var_samp('nan'::float8);
- var_pop | var_samp
- ---------+----------
- NaN |
- (1 row)
- SELECT stddev_pop('nan'::float8), stddev_samp('nan'::float8);
- stddev_pop | stddev_samp
- ------------+-------------
- NaN |
- (1 row)
- SELECT var_pop(1.0::float4), var_samp(2.0::float4);
- var_pop | var_samp
- ---------+----------
- 0 |
- (1 row)
- SELECT stddev_pop(3.0::float4), stddev_samp(4.0::float4);
- stddev_pop | stddev_samp
- ------------+-------------
- 0 |
- (1 row)
- SELECT var_pop('inf'::float4), var_samp('inf'::float4);
- var_pop | var_samp
- ---------+----------
- NaN |
- (1 row)
- SELECT stddev_pop('inf'::float4), stddev_samp('inf'::float4);
- stddev_pop | stddev_samp
- ------------+-------------
- NaN |
- (1 row)
- SELECT var_pop('nan'::float4), var_samp('nan'::float4);
- var_pop | var_samp
- ---------+----------
- NaN |
- (1 row)
- SELECT stddev_pop('nan'::float4), stddev_samp('nan'::float4);
- stddev_pop | stddev_samp
- ------------+-------------
- NaN |
- (1 row)
- SELECT var_pop(1.0::numeric), var_samp(2.0::numeric);
- var_pop | var_samp
- ---------+----------
- 0 |
- (1 row)
- SELECT stddev_pop(3.0::numeric), stddev_samp(4.0::numeric);
- stddev_pop | stddev_samp
- ------------+-------------
- 0 |
- (1 row)
- SELECT var_pop('inf'::numeric), var_samp('inf'::numeric);
- var_pop | var_samp
- ---------+----------
- NaN |
- (1 row)
- SELECT stddev_pop('inf'::numeric), stddev_samp('inf'::numeric);
- stddev_pop | stddev_samp
- ------------+-------------
- NaN |
- (1 row)
- SELECT var_pop('nan'::numeric), var_samp('nan'::numeric);
- var_pop | var_samp
- ---------+----------
- NaN |
- (1 row)
- SELECT stddev_pop('nan'::numeric), stddev_samp('nan'::numeric);
- stddev_pop | stddev_samp
- ------------+-------------
- NaN |
- (1 row)
- -- verify correct results for null and NaN inputs
- select sum(null::int4) from generate_series(1,3);
- sum
- -----
-
- (1 row)
- select sum(null::int8) from generate_series(1,3);
- sum
- -----
-
- (1 row)
- select sum(null::numeric) from generate_series(1,3);
- sum
- -----
-
- (1 row)
- select sum(null::float8) from generate_series(1,3);
- sum
- -----
-
- (1 row)
- select avg(null::int4) from generate_series(1,3);
- avg
- -----
-
- (1 row)
- select avg(null::int8) from generate_series(1,3);
- avg
- -----
-
- (1 row)
- select avg(null::numeric) from generate_series(1,3);
- avg
- -----
-
- (1 row)
- select avg(null::float8) from generate_series(1,3);
- avg
- -----
-
- (1 row)
- select sum('NaN'::numeric) from generate_series(1,3);
- sum
- -----
- NaN
- (1 row)
- select avg('NaN'::numeric) from generate_series(1,3);
- avg
- -----
- NaN
- (1 row)
- -- verify correct results for infinite inputs
- SELECT sum(x::float8), avg(x::float8), var_pop(x::float8)
- FROM (VALUES ('1'), ('infinity')) v(x);
- sum | avg | var_pop
- ----------+----------+---------
- Infinity | Infinity | NaN
- (1 row)
- SELECT sum(x::float8), avg(x::float8), var_pop(x::float8)
- FROM (VALUES ('infinity'), ('1')) v(x);
- sum | avg | var_pop
- ----------+----------+---------
- Infinity | Infinity | NaN
- (1 row)
- SELECT sum(x::float8), avg(x::float8), var_pop(x::float8)
- FROM (VALUES ('infinity'), ('infinity')) v(x);
- sum | avg | var_pop
- ----------+----------+---------
- Infinity | Infinity | NaN
- (1 row)
- SELECT sum(x::float8), avg(x::float8), var_pop(x::float8)
- FROM (VALUES ('-infinity'), ('infinity')) v(x);
- sum | avg | var_pop
- -----+-----+---------
- NaN | NaN | NaN
- (1 row)
- SELECT sum(x::float8), avg(x::float8), var_pop(x::float8)
- FROM (VALUES ('-infinity'), ('-infinity')) v(x);
- sum | avg | var_pop
- -----------+-----------+---------
- -Infinity | -Infinity | NaN
- (1 row)
- SELECT sum(x::numeric), avg(x::numeric), var_pop(x::numeric)
- FROM (VALUES ('1'), ('infinity')) v(x);
- sum | avg | var_pop
- ----------+----------+---------
- Infinity | Infinity | NaN
- (1 row)
- SELECT sum(x::numeric), avg(x::numeric), var_pop(x::numeric)
- FROM (VALUES ('infinity'), ('1')) v(x);
- sum | avg | var_pop
- ----------+----------+---------
- Infinity | Infinity | NaN
- (1 row)
- SELECT sum(x::numeric), avg(x::numeric), var_pop(x::numeric)
- FROM (VALUES ('infinity'), ('infinity')) v(x);
- sum | avg | var_pop
- ----------+----------+---------
- Infinity | Infinity | NaN
- (1 row)
- SELECT sum(x::numeric), avg(x::numeric), var_pop(x::numeric)
- FROM (VALUES ('-infinity'), ('infinity')) v(x);
- sum | avg | var_pop
- -----+-----+---------
- NaN | NaN | NaN
- (1 row)
- SELECT sum(x::numeric), avg(x::numeric), var_pop(x::numeric)
- FROM (VALUES ('-infinity'), ('-infinity')) v(x);
- sum | avg | var_pop
- -----------+-----------+---------
- -Infinity | -Infinity | NaN
- (1 row)
- -- test accuracy with a large input offset
- SELECT avg(x::float8), var_pop(x::float8)
- FROM (VALUES (100000003), (100000004), (100000006), (100000007)) v(x);
- avg | var_pop
- -----------+---------
- 100000005 | 2.5
- (1 row)
- SELECT avg(x::float8), var_pop(x::float8)
- FROM (VALUES (7000000000005), (7000000000007)) v(x);
- avg | var_pop
- ---------------+---------
- 7000000000006 | 1
- (1 row)
- -- SQL2003 binary aggregates
- SELECT regr_count(b, a) FROM aggtest;
- regr_count
- ------------
- 4
- (1 row)
- SELECT regr_sxx(b, a) FROM aggtest;
- regr_sxx
- ----------
- 5099
- (1 row)
- SELECT regr_syy(b, a) FROM aggtest;
- regr_syy
- ------------------
- 68756.2156939293
- (1 row)
- SELECT regr_sxy(b, a) FROM aggtest;
- regr_sxy
- ------------------
- 2614.51582155004
- (1 row)
- SELECT regr_avgx(b, a), regr_avgy(b, a) FROM aggtest;
- regr_avgx | regr_avgy
- -----------+------------------
- 49.5 | 107.943152273074
- (1 row)
- SELECT regr_r2(b, a) FROM aggtest;
- regr_r2
- --------------------
- 0.0194977982031803
- (1 row)
- SELECT regr_slope(b, a), regr_intercept(b, a) FROM aggtest;
- regr_slope | regr_intercept
- -------------------+------------------
- 0.512750700441271 | 82.5619926012309
- (1 row)
- SELECT covar_pop(b, a), covar_samp(b, a) FROM aggtest;
- covar_pop | covar_samp
- -----------------+------------------
- 653.62895538751 | 871.505273850014
- (1 row)
- SELECT corr(b, a) FROM aggtest;
- corr
- -------------------
- 0.139634516517873
- (1 row)
- -- check single-tuple behavior
- SELECT covar_pop(1::float8,2::float8), covar_samp(3::float8,4::float8);
- covar_pop | covar_samp
- -----------+------------
- 0 |
- (1 row)
- SELECT covar_pop(1::float8,'inf'::float8), covar_samp(3::float8,'inf'::float8);
- covar_pop | covar_samp
- -----------+------------
- NaN |
- (1 row)
- SELECT covar_pop(1::float8,'nan'::float8), covar_samp(3::float8,'nan'::float8);
- covar_pop | covar_samp
- -----------+------------
- NaN |
- (1 row)
- -- test accum and combine functions directly
- CREATE TABLE regr_test (x float8, y float8);
- INSERT INTO regr_test VALUES (10,150),(20,250),(30,350),(80,540),(100,200);
- SELECT count(*), sum(x), regr_sxx(y,x), sum(y),regr_syy(y,x), regr_sxy(y,x)
- FROM regr_test WHERE x IN (10,20,30,80);
- count | sum | regr_sxx | sum | regr_syy | regr_sxy
- -------+-----+----------+------+----------+----------
- 4 | 140 | 2900 | 1290 | 83075 | 15050
- (1 row)
- SELECT count(*), sum(x), regr_sxx(y,x), sum(y),regr_syy(y,x), regr_sxy(y,x)
- FROM regr_test;
- count | sum | regr_sxx | sum | regr_syy | regr_sxy
- -------+-----+----------+------+----------+----------
- 5 | 240 | 6280 | 1490 | 95080 | 8680
- (1 row)
- SELECT float8_accum('{4,140,2900}'::float8[], 100);
- float8_accum
- --------------
- {5,240,6280}
- (1 row)
- SELECT float8_regr_accum('{4,140,2900,1290,83075,15050}'::float8[], 200, 100);
- float8_regr_accum
- ------------------------------
- {5,240,6280,1490,95080,8680}
- (1 row)
- SELECT count(*), sum(x), regr_sxx(y,x), sum(y),regr_syy(y,x), regr_sxy(y,x)
- FROM regr_test WHERE x IN (10,20,30);
- count | sum | regr_sxx | sum | regr_syy | regr_sxy
- -------+-----+----------+-----+----------+----------
- 3 | 60 | 200 | 750 | 20000 | 2000
- (1 row)
- SELECT count(*), sum(x), regr_sxx(y,x), sum(y),regr_syy(y,x), regr_sxy(y,x)
- FROM regr_test WHERE x IN (80,100);
- count | sum | regr_sxx | sum | regr_syy | regr_sxy
- -------+-----+----------+-----+----------+----------
- 2 | 180 | 200 | 740 | 57800 | -3400
- (1 row)
- SELECT float8_combine('{3,60,200}'::float8[], '{0,0,0}'::float8[]);
- float8_combine
- ----------------
- {3,60,200}
- (1 row)
- SELECT float8_combine('{0,0,0}'::float8[], '{2,180,200}'::float8[]);
- float8_combine
- ----------------
- {2,180,200}
- (1 row)
- SELECT float8_combine('{3,60,200}'::float8[], '{2,180,200}'::float8[]);
- float8_combine
- ----------------
- {5,240,6280}
- (1 row)
- SELECT float8_regr_combine('{3,60,200,750,20000,2000}'::float8[],
- '{0,0,0,0,0,0}'::float8[]);
- float8_regr_combine
- ---------------------------
- {3,60,200,750,20000,2000}
- (1 row)
- SELECT float8_regr_combine('{0,0,0,0,0,0}'::float8[],
- '{2,180,200,740,57800,-3400}'::float8[]);
- float8_regr_combine
- -----------------------------
- {2,180,200,740,57800,-3400}
- (1 row)
- SELECT float8_regr_combine('{3,60,200,750,20000,2000}'::float8[],
- '{2,180,200,740,57800,-3400}'::float8[]);
- float8_regr_combine
- ------------------------------
- {5,240,6280,1490,95080,8680}
- (1 row)
- DROP TABLE regr_test;
- -- test count, distinct
- SELECT count(four) AS cnt_1000 FROM onek;
- cnt_1000
- ----------
- 1000
- (1 row)
- SELECT count(DISTINCT four) AS cnt_4 FROM onek;
- cnt_4
- -------
- 4
- (1 row)
- select ten, count(*), sum(four) from onek
- group by ten order by ten;
- ten | count | sum
- -----+-------+-----
- 0 | 100 | 100
- 1 | 100 | 200
- 2 | 100 | 100
- 3 | 100 | 200
- 4 | 100 | 100
- 5 | 100 | 200
- 6 | 100 | 100
- 7 | 100 | 200
- 8 | 100 | 100
- 9 | 100 | 200
- (10 rows)
- select ten, count(four), sum(DISTINCT four) from onek
- group by ten order by ten;
- ten | count | sum
- -----+-------+-----
- 0 | 100 | 2
- 1 | 100 | 4
- 2 | 100 | 2
- 3 | 100 | 4
- 4 | 100 | 2
- 5 | 100 | 4
- 6 | 100 | 2
- 7 | 100 | 4
- 8 | 100 | 2
- 9 | 100 | 4
- (10 rows)
- -- user-defined aggregates
- SELECT newavg(four) AS avg_1 FROM onek;
- avg_1
- --------------------
- 1.5000000000000000
- (1 row)
- SELECT newsum(four) AS sum_1500 FROM onek;
- sum_1500
- ----------
- 1500
- (1 row)
- SELECT newcnt(four) AS cnt_1000 FROM onek;
- cnt_1000
- ----------
- 1000
- (1 row)
- SELECT newcnt(*) AS cnt_1000 FROM onek;
- cnt_1000
- ----------
- 1000
- (1 row)
- SELECT oldcnt(*) AS cnt_1000 FROM onek;
- cnt_1000
- ----------
- 1000
- (1 row)
- SELECT sum2(q1,q2) FROM int8_tbl;
- sum2
- -------------------
- 18271560493827981
- (1 row)
- -- test for outer-level aggregates
- -- this should work
- select ten, sum(distinct four) from onek a
- group by ten
- having exists (select 1 from onek b where sum(distinct a.four) = b.four);
- ten | sum
- -----+-----
- 0 | 2
- 2 | 2
- 4 | 2
- 6 | 2
- 8 | 2
- (5 rows)
- -- this should fail because subquery has an agg of its own in WHERE
- select ten, sum(distinct four) from onek a
- group by ten
- having exists (select 1 from onek b
- where sum(distinct a.four + b.four) = b.four);
- ERROR: aggregate functions are not allowed in WHERE
- LINE 4: where sum(distinct a.four + b.four) = b.four)...
- ^
- -- Test handling of sublinks within outer-level aggregates.
- -- Per bug report from Daniel Grace.
- select
- (select max((select i.unique2 from tenk1 i where i.unique1 = o.unique1)))
- from tenk1 o;
- max
- ------
- 9999
- (1 row)
- -- Test handling of Params within aggregate arguments in hashed aggregation.
- -- Per bug report from Jeevan Chalke.
- explain (verbose, costs off)
- select s1, s2, sm
- from generate_series(1, 3) s1,
- lateral (select s2, sum(s1 + s2) sm
- from generate_series(1, 3) s2 group by s2) ss
- order by 1, 2;
- QUERY PLAN
- ------------------------------------------------------------------
- Sort
- Output: s1.s1, s2.s2, (sum((s1.s1 + s2.s2)))
- Sort Key: s1.s1, s2.s2
- -> Nested Loop
- Output: s1.s1, s2.s2, (sum((s1.s1 + s2.s2)))
- -> Function Scan on pg_catalog.generate_series s1
- Output: s1.s1
- Function Call: generate_series(1, 3)
- -> HashAggregate
- Output: s2.s2, sum((s1.s1 + s2.s2))
- Group Key: s2.s2
- -> Function Scan on pg_catalog.generate_series s2
- Output: s2.s2
- Function Call: generate_series(1, 3)
- (14 rows)
- select s1, s2, sm
- from generate_series(1, 3) s1,
- lateral (select s2, sum(s1 + s2) sm
- from generate_series(1, 3) s2 group by s2) ss
- order by 1, 2;
- s1 | s2 | sm
- ----+----+----
- 1 | 1 | 2
- 1 | 2 | 3
- 1 | 3 | 4
- 2 | 1 | 3
- 2 | 2 | 4
- 2 | 3 | 5
- 3 | 1 | 4
- 3 | 2 | 5
- 3 | 3 | 6
- (9 rows)
- explain (verbose, costs off)
- select array(select sum(x+y) s
- from generate_series(1,3) y group by y order by s)
- from generate_series(1,3) x;
- QUERY PLAN
- -------------------------------------------------------------------
- Function Scan on pg_catalog.generate_series x
- Output: (SubPlan 1)
- Function Call: generate_series(1, 3)
- SubPlan 1
- -> Sort
- Output: (sum((x.x + y.y))), y.y
- Sort Key: (sum((x.x + y.y)))
- -> HashAggregate
- Output: sum((x.x + y.y)), y.y
- Group Key: y.y
- -> Function Scan on pg_catalog.generate_series y
- Output: y.y
- Function Call: generate_series(1, 3)
- (13 rows)
- select array(select sum(x+y) s
- from generate_series(1,3) y group by y order by s)
- from generate_series(1,3) x;
- array
- ---------
- {2,3,4}
- {3,4,5}
- {4,5,6}
- (3 rows)
- --
- -- test for bitwise integer aggregates
- --
- CREATE TEMPORARY TABLE bitwise_test(
- i2 INT2,
- i4 INT4,
- i8 INT8,
- i INTEGER,
- x INT2,
- y BIT(4)
- );
- -- empty case
- SELECT
- BIT_AND(i2) AS "?",
- BIT_OR(i4) AS "?",
- BIT_XOR(i8) AS "?"
- FROM bitwise_test;
- ? | ? | ?
- ---+---+---
- | |
- (1 row)
- COPY bitwise_test FROM STDIN NULL 'null';
- SELECT
- BIT_AND(i2) AS "1",
- BIT_AND(i4) AS "1",
- BIT_AND(i8) AS "1",
- BIT_AND(i) AS "?",
- BIT_AND(x) AS "0",
- BIT_AND(y) AS "0100",
- BIT_OR(i2) AS "7",
- BIT_OR(i4) AS "7",
- BIT_OR(i8) AS "7",
- BIT_OR(i) AS "?",
- BIT_OR(x) AS "7",
- BIT_OR(y) AS "1101",
- BIT_XOR(i2) AS "5",
- BIT_XOR(i4) AS "5",
- BIT_XOR(i8) AS "5",
- BIT_XOR(i) AS "?",
- BIT_XOR(x) AS "7",
- BIT_XOR(y) AS "1101"
- FROM bitwise_test;
- 1 | 1 | 1 | ? | 0 | 0100 | 7 | 7 | 7 | ? | 7 | 1101 | 5 | 5 | 5 | ? | 7 | 1101
- ---+---+---+---+---+------+---+---+---+---+---+------+---+---+---+---+---+------
- 1 | 1 | 1 | 1 | 0 | 0100 | 7 | 7 | 7 | 3 | 7 | 1101 | 5 | 5 | 5 | 2 | 7 | 1101
- (1 row)
- --
- -- test boolean aggregates
- --
- -- first test all possible transition and final states
- SELECT
- -- boolean and transitions
- -- null because strict
- booland_statefunc(NULL, NULL) IS NULL AS "t",
- booland_statefunc(TRUE, NULL) IS NULL AS "t",
- booland_statefunc(FALSE, NULL) IS NULL AS "t",
- booland_statefunc(NULL, TRUE) IS NULL AS "t",
- booland_statefunc(NULL, FALSE) IS NULL AS "t",
- -- and actual computations
- booland_statefunc(TRUE, TRUE) AS "t",
- NOT booland_statefunc(TRUE, FALSE) AS "t",
- NOT booland_statefunc(FALSE, TRUE) AS "t",
- NOT booland_statefunc(FALSE, FALSE) AS "t";
- t | t | t | t | t | t | t | t | t
- ---+---+---+---+---+---+---+---+---
- t | t | t | t | t | t | t | t | t
- (1 row)
- SELECT
- -- boolean or transitions
- -- null because strict
- boolor_statefunc(NULL, NULL) IS NULL AS "t",
- boolor_statefunc(TRUE, NULL) IS NULL AS "t",
- boolor_statefunc(FALSE, NULL) IS NULL AS "t",
- boolor_statefunc(NULL, TRUE) IS NULL AS "t",
- boolor_statefunc(NULL, FALSE) IS NULL AS "t",
- -- actual computations
- boolor_statefunc(TRUE, TRUE) AS "t",
- boolor_statefunc(TRUE, FALSE) AS "t",
- boolor_statefunc(FALSE, TRUE) AS "t",
- NOT boolor_statefunc(FALSE, FALSE) AS "t";
- t | t | t | t | t | t | t | t | t
- ---+---+---+---+---+---+---+---+---
- t | t | t | t | t | t | t | t | t
- (1 row)
- CREATE TEMPORARY TABLE bool_test(
- b1 BOOL,
- b2 BOOL,
- b3 BOOL,
- b4 BOOL);
- -- empty case
- SELECT
- BOOL_AND(b1) AS "n",
- BOOL_OR(b3) AS "n"
- FROM bool_test;
- n | n
- ---+---
- |
- (1 row)
- COPY bool_test FROM STDIN NULL 'null';
- SELECT
- BOOL_AND(b1) AS "f",
- BOOL_AND(b2) AS "t",
- BOOL_AND(b3) AS "f",
- BOOL_AND(b4) AS "n",
- BOOL_AND(NOT b2) AS "f",
- BOOL_AND(NOT b3) AS "t"
- FROM bool_test;
- f | t | f | n | f | t
- ---+---+---+---+---+---
- f | t | f | | f | t
- (1 row)
- SELECT
- EVERY(b1) AS "f",
- EVERY(b2) AS "t",
- EVERY(b3) AS "f",
- EVERY(b4) AS "n",
- EVERY(NOT b2) AS "f",
- EVERY(NOT b3) AS "t"
- FROM bool_test;
- f | t | f | n | f | t
- ---+---+---+---+---+---
- f | t | f | | f | t
- (1 row)
- SELECT
- BOOL_OR(b1) AS "t",
- BOOL_OR(b2) AS "t",
- BOOL_OR(b3) AS "f",
- BOOL_OR(b4) AS "n",
- BOOL_OR(NOT b2) AS "f",
- BOOL_OR(NOT b3) AS "t"
- FROM bool_test;
- t | t | f | n | f | t
- ---+---+---+---+---+---
- t | t | f | | f | t
- (1 row)
- --
- -- Test cases that should be optimized into indexscans instead of
- -- the generic aggregate implementation.
- --
- -- Basic cases
- explain (costs off)
- select min(unique1) from tenk1;
- QUERY PLAN
- ------------------------------------------------------------
- Result
- InitPlan 1 (returns $0)
- -> Limit
- -> Index Only Scan using tenk1_unique1 on tenk1
- Index Cond: (unique1 IS NOT NULL)
- (5 rows)
- select min(unique1) from tenk1;
- min
- -----
- 0
- (1 row)
- explain (costs off)
- select max(unique1) from tenk1;
- QUERY PLAN
- ---------------------------------------------------------------------
- Result
- InitPlan 1 (returns $0)
- -> Limit
- -> Index Only Scan Backward using tenk1_unique1 on tenk1
- Index Cond: (unique1 IS NOT NULL)
- (5 rows)
- select max(unique1) from tenk1;
- max
- ------
- 9999
- (1 row)
- explain (costs off)
- select max(unique1) from tenk1 where unique1 < 42;
- QUERY PLAN
- ------------------------------------------------------------------------
- Result
- InitPlan 1 (returns $0)
- -> Limit
- -> Index Only Scan Backward using tenk1_unique1 on tenk1
- Index Cond: ((unique1 IS NOT NULL) AND (unique1 < 42))
- (5 rows)
- select max(unique1) from tenk1 where unique1 < 42;
- max
- -----
- 41
- (1 row)
- explain (costs off)
- select max(unique1) from tenk1 where unique1 > 42;
- QUERY PLAN
- ------------------------------------------------------------------------
- Result
- InitPlan 1 (returns $0)
- -> Limit
- -> Index Only Scan Backward using tenk1_unique1 on tenk1
- Index Cond: ((unique1 IS NOT NULL) AND (unique1 > 42))
- (5 rows)
- select max(unique1) from tenk1 where unique1 > 42;
- max
- ------
- 9999
- (1 row)
- -- the planner may choose a generic aggregate here if parallel query is
- -- enabled, since that plan will be parallel safe and the "optimized"
- -- plan, which has almost identical cost, will not be. we want to test
- -- the optimized plan, so temporarily disable parallel query.
- begin;
- set local max_parallel_workers_per_gather = 0;
- explain (costs off)
- select max(unique1) from tenk1 where unique1 > 42000;
- QUERY PLAN
- ---------------------------------------------------------------------------
- Result
- InitPlan 1 (returns $0)
- -> Limit
- -> Index Only Scan Backward using tenk1_unique1 on tenk1
- Index Cond: ((unique1 IS NOT NULL) AND (unique1 > 42000))
- (5 rows)
- select max(unique1) from tenk1 where unique1 > 42000;
- max
- -----
-
- (1 row)
- rollback;
- -- multi-column index (uses tenk1_thous_tenthous)
- explain (costs off)
- select max(tenthous) from tenk1 where thousand = 33;
- QUERY PLAN
- ----------------------------------------------------------------------------
- Result
- InitPlan 1 (returns $0)
- -> Limit
- -> Index Only Scan Backward using tenk1_thous_tenthous on tenk1
- Index Cond: ((thousand = 33) AND (tenthous IS NOT NULL))
- (5 rows)
- select max(tenthous) from tenk1 where thousand = 33;
- max
- ------
- 9033
- (1 row)
- explain (costs off)
- select min(tenthous) from tenk1 where thousand = 33;
- QUERY PLAN
- --------------------------------------------------------------------------
- Result
- InitPlan 1 (returns $0)
- -> Limit
- -> Index Only Scan using tenk1_thous_tenthous on tenk1
- Index Cond: ((thousand = 33) AND (tenthous IS NOT NULL))
- (5 rows)
- select min(tenthous) from tenk1 where thousand = 33;
- min
- -----
- 33
- (1 row)
- -- check parameter propagation into an indexscan subquery
- explain (costs off)
- select f1, (select min(unique1) from tenk1 where unique1 > f1) AS gt
- from int4_tbl;
- QUERY PLAN
- -----------------------------------------------------------------------------------------
- Seq Scan on int4_tbl
- SubPlan 2
- -> Result
- InitPlan 1 (returns $1)
- -> Limit
- -> Index Only Scan using tenk1_unique1 on tenk1
- Index Cond: ((unique1 IS NOT NULL) AND (unique1 > int4_tbl.f1))
- (7 rows)
- select f1, (select min(unique1) from tenk1 where unique1 > f1) AS gt
- from int4_tbl;
- f1 | gt
- -------------+----
- 0 | 1
- 123456 |
- -123456 | 0
- 2147483647 |
- -2147483647 | 0
- (5 rows)
- -- check some cases that were handled incorrectly in 8.3.0
- explain (costs off)
- select distinct max(unique2) from tenk1;
- QUERY PLAN
- ---------------------------------------------------------------------
- HashAggregate
- Group Key: $0
- InitPlan 1 (returns $0)
- -> Limit
- -> Index Only Scan Backward using tenk1_unique2 on tenk1
- Index Cond: (unique2 IS NOT NULL)
- -> Result
- (7 rows)
- select distinct max(unique2) from tenk1;
- max
- ------
- 9999
- (1 row)
- explain (costs off)
- select max(unique2) from tenk1 order by 1;
- QUERY PLAN
- ---------------------------------------------------------------------
- Sort
- Sort Key: ($0)
- InitPlan 1 (returns $0)
- -> Limit
- -> Index Only Scan Backward using tenk1_unique2 on tenk1
- Index Cond: (unique2 IS NOT NULL)
- -> Result
- (7 rows)
- select max(unique2) from tenk1 order by 1;
- max
- ------
- 9999
- (1 row)
- explain (costs off)
- select max(unique2) from tenk1 order by max(unique2);
- QUERY PLAN
- ---------------------------------------------------------------------
- Sort
- Sort Key: ($0)
- InitPlan 1 (returns $0)
- -> Limit
- -> Index Only Scan Backward using tenk1_unique2 on tenk1
- Index Cond: (unique2 IS NOT NULL)
- -> Result
- (7 rows)
- select max(unique2) from tenk1 order by max(unique2);
- max
- ------
- 9999
- (1 row)
- explain (costs off)
- select max(unique2) from tenk1 order by max(unique2)+1;
- QUERY PLAN
- ---------------------------------------------------------------------
- Sort
- Sort Key: (($0 + 1))
- InitPlan 1 (returns $0)
- -> Limit
- -> Index Only Scan Backward using tenk1_unique2 on tenk1
- Index Cond: (unique2 IS NOT NULL)
- -> Result
- (7 rows)
- select max(unique2) from tenk1 order by max(unique2)+1;
- max
- ------
- 9999
- (1 row)
- explain (costs off)
- select max(unique2), generate_series(1,3) as g from tenk1 order by g desc;
- QUERY PLAN
- ---------------------------------------------------------------------
- Sort
- Sort Key: (generate_series(1, 3)) DESC
- InitPlan 1 (returns $0)
- -> Limit
- -> Index Only Scan Backward using tenk1_unique2 on tenk1
- Index Cond: (unique2 IS NOT NULL)
- -> ProjectSet
- -> Result
- (8 rows)
- select max(unique2), generate_series(1,3) as g from tenk1 order by g desc;
- max | g
- ------+---
- 9999 | 3
- 9999 | 2
- 9999 | 1
- (3 rows)
- -- interesting corner case: constant gets optimized into a seqscan
- explain (costs off)
- select max(100) from tenk1;
- QUERY PLAN
- ----------------------------------------------------
- Result
- InitPlan 1 (returns $0)
- -> Limit
- -> Result
- One-Time Filter: (100 IS NOT NULL)
- -> Seq Scan on tenk1
- (6 rows)
- select max(100) from tenk1;
- max
- -----
- 100
- (1 row)
- -- try it on an inheritance tree
- create table minmaxtest(f1 int);
- create table minmaxtest1() inherits (minmaxtest);
- create table minmaxtest2() inherits (minmaxtest);
- create table minmaxtest3() inherits (minmaxtest);
- create index minmaxtesti on minmaxtest(f1);
- create index minmaxtest1i on minmaxtest1(f1);
- create index minmaxtest2i on minmaxtest2(f1 desc);
- create index minmaxtest3i on minmaxtest3(f1) where f1 is not null;
- insert into minmaxtest values(11), (12);
- insert into minmaxtest1 values(13), (14);
- insert into minmaxtest2 values(15), (16);
- insert into minmaxtest3 values(17), (18);
- explain (costs off)
- select min(f1), max(f1) from minmaxtest;
- QUERY PLAN
- ---------------------------------------------------------------------------------------------
- Result
- InitPlan 1 (returns $0)
- -> Limit
- -> Merge Append
- Sort Key: minmaxtest.f1
- -> Index Only Scan using minmaxtesti on minmaxtest minmaxtest_1
- Index Cond: (f1 IS NOT NULL)
- -> Index Only Scan using minmaxtest1i on minmaxtest1 minmaxtest_2
- Index Cond: (f1 IS NOT NULL)
- -> Index Only Scan Backward using minmaxtest2i on minmaxtest2 minmaxtest_3
- Index Cond: (f1 IS NOT NULL)
- -> Index Only Scan using minmaxtest3i on minmaxtest3 minmaxtest_4
- InitPlan 2 (returns $1)
- -> Limit
- -> Merge Append
- Sort Key: minmaxtest_5.f1 DESC
- -> Index Only Scan Backward using minmaxtesti on minmaxtest minmaxtest_6
- Index Cond: (f1 IS NOT NULL)
- -> Index Only Scan Backward using minmaxtest1i on minmaxtest1 minmaxtest_7
- Index Cond: (f1 IS NOT NULL)
- -> Index Only Scan using minmaxtest2i on minmaxtest2 minmaxtest_8
- Index Cond: (f1 IS NOT NULL)
- -> Index Only Scan Backward using minmaxtest3i on minmaxtest3 minmaxtest_9
- (23 rows)
- select min(f1), max(f1) from minmaxtest;
- min | max
- -----+-----
- 11 | 18
- (1 row)
- -- DISTINCT doesn't do anything useful here, but it shouldn't fail
- explain (costs off)
- select distinct min(f1), max(f1) from minmaxtest;
- QUERY PLAN
- ---------------------------------------------------------------------------------------------
- Unique
- InitPlan 1 (returns $0)
- -> Limit
- -> Merge Append
- Sort Key: minmaxtest.f1
- -> Index Only Scan using minmaxtesti on minmaxtest minmaxtest_1
- Index Cond: (f1 IS NOT NULL)
- -> Index Only Scan using minmaxtest1i on minmaxtest1 minmaxtest_2
- Index Cond: (f1 IS NOT NULL)
- -> Index Only Scan Backward using minmaxtest2i on minmaxtest2 minmaxtest_3
- Index Cond: (f1 IS NOT NULL)
- -> Index Only Scan using minmaxtest3i on minmaxtest3 minmaxtest_4
- InitPlan 2 (returns $1)
- -> Limit
- -> Merge Append
- Sort Key: minmaxtest_5.f1 DESC
- -> Index Only Scan Backward using minmaxtesti on minmaxtest minmaxtest_6
- Index Cond: (f1 IS NOT NULL)
- -> Index Only Scan Backward using minmaxtest1i on minmaxtest1 minmaxtest_7
- Index Cond: (f1 IS NOT NULL)
- -> Index Only Scan using minmaxtest2i on minmaxtest2 minmaxtest_8
- Index Cond: (f1 IS NOT NULL)
- -> Index Only Scan Backward using minmaxtest3i on minmaxtest3 minmaxtest_9
- -> Sort
- Sort Key: ($0), ($1)
- -> Result
- (26 rows)
- select distinct min(f1), max(f1) from minmaxtest;
- min | max
- -----+-----
- 11 | 18
- (1 row)
- drop table minmaxtest cascade;
- NOTICE: drop cascades to 3 other objects
- DETAIL: drop cascades to table minmaxtest1
- drop cascades to table minmaxtest2
- drop cascades to table minmaxtest3
- -- check for correct detection of nested-aggregate errors
- select max(min(unique1)) from tenk1;
- ERROR: aggregate function calls cannot be nested
- LINE 1: select max(min(unique1)) from tenk1;
- ^
- select (select max(min(unique1)) from int8_tbl) from tenk1;
- ERROR: aggregate function calls cannot be nested
- LINE 1: select (select max(min(unique1)) from int8_tbl) from tenk1;
- ^
- --
- -- Test removal of redundant GROUP BY columns
- --
- create temp table t1 (a int, b int, c int, d int, primary key (a, b));
- create temp table t2 (x int, y int, z int, primary key (x, y));
- create temp table t3 (a int, b int, c int, primary key(a, b) deferrable);
- -- Non-primary-key columns can be removed from GROUP BY
- explain (costs off) select * from t1 group by a,b,c,d;
- QUERY PLAN
- ----------------------
- HashAggregate
- Group Key: a, b
- -> Seq Scan on t1
- (3 rows)
- -- No removal can happen if the complete PK is not present in GROUP BY
- explain (costs off) select a,c from t1 group by a,c,d;
- QUERY PLAN
- ----------------------
- HashAggregate
- Group Key: a, c, d
- -> Seq Scan on t1
- (3 rows)
- -- Test removal across multiple relations
- explain (costs off) select *
- from t1 inner join t2 on t1.a = t2.x and t1.b = t2.y
- group by t1.a,t1.b,t1.c,t1.d,t2.x,t2.y,t2.z;
- QUERY PLAN
- ------------------------------------------------------
- HashAggregate
- Group Key: t1.a, t1.b, t2.x, t2.y
- -> Hash Join
- Hash Cond: ((t2.x = t1.a) AND (t2.y = t1.b))
- -> Seq Scan on t2
- -> Hash
- -> Seq Scan on t1
- (7 rows)
- -- Test case where t1 can be optimized but not t2
- explain (costs off) select t1.*,t2.x,t2.z
- from t1 inner join t2 on t1.a = t2.x and t1.b = t2.y
- group by t1.a,t1.b,t1.c,t1.d,t2.x,t2.z;
- QUERY PLAN
- ------------------------------------------------------
- HashAggregate
- Group Key: t1.a, t1.b, t2.x, t2.z
- -> Hash Join
- Hash Cond: ((t2.x = t1.a) AND (t2.y = t1.b))
- -> Seq Scan on t2
- -> Hash
- -> Seq Scan on t1
- (7 rows)
- -- Cannot optimize when PK is deferrable
- explain (costs off) select * from t3 group by a,b,c;
- QUERY PLAN
- ----------------------
- HashAggregate
- Group Key: a, b, c
- -> Seq Scan on t3
- (3 rows)
- create temp table t1c () inherits (t1);
- -- Ensure we don't remove any columns when t1 has a child table
- explain (costs off) select * from t1 group by a,b,c,d;
- QUERY PLAN
- -------------------------------------
- HashAggregate
- Group Key: t1.a, t1.b, t1.c, t1.d
- -> Append
- -> Seq Scan on t1 t1_1
- -> Seq Scan on t1c t1_2
- (5 rows)
- -- Okay to remove columns if we're only querying the parent.
- explain (costs off) select * from only t1 group by a,b,c,d;
- QUERY PLAN
- ----------------------
- HashAggregate
- Group Key: a, b
- -> Seq Scan on t1
- (3 rows)
- create temp table p_t1 (
- a int,
- b int,
- c int,
- d int,
- primary key(a,b)
- ) partition by list(a);
- create temp table p_t1_1 partition of p_t1 for values in(1);
- create temp table p_t1_2 partition of p_t1 for values in(2);
- -- Ensure we can remove non-PK columns for partitioned tables.
- explain (costs off) select * from p_t1 group by a,b,c,d;
- QUERY PLAN
- --------------------------------
- HashAggregate
- Group Key: p_t1.a, p_t1.b
- -> Append
- -> Seq Scan on p_t1_1
- -> Seq Scan on p_t1_2
- (5 rows)
- drop table t1 cascade;
- NOTICE: drop cascades to table t1c
- drop table t2;
- drop table t3;
- drop table p_t1;
- --
- -- Test GROUP BY matching of join columns that are type-coerced due to USING
- --
- create temp table t1(f1 int, f2 bigint);
- create temp table t2(f1 bigint, f22 bigint);
- select f1 from t1 left join t2 using (f1) group by f1;
- f1
- ----
- (0 rows)
- select f1 from t1 left join t2 using (f1) group by t1.f1;
- f1
- ----
- (0 rows)
- select t1.f1 from t1 left join t2 using (f1) group by t1.f1;
- f1
- ----
- (0 rows)
- -- only this one should fail:
- select t1.f1 from t1 left join t2 using (f1) group by f1;
- ERROR: column "t1.f1" must appear in the GROUP BY clause or be used in an aggregate function
- LINE 1: select t1.f1 from t1 left join t2 using (f1) group by f1;
- ^
- drop table t1, t2;
- --
- -- Test combinations of DISTINCT and/or ORDER BY
- --
- select array_agg(a order by b)
- from (values (1,4),(2,3),(3,1),(4,2)) v(a,b);
- array_agg
- -----------
- {3,4,2,1}
- (1 row)
- select array_agg(a order by a)
- from (values (1,4),(2,3),(3,1),(4,2)) v(a,b);
- array_agg
- -----------
- {1,2,3,4}
- (1 row)
- select array_agg(a order by a desc)
- from (values (1,4),(2,3),(3,1),(4,2)) v(a,b);
- array_agg
- -----------
- {4,3,2,1}
- (1 row)
- select array_agg(b order by a desc)
- from (values (1,4),(2,3),(3,1),(4,2)) v(a,b);
- array_agg
- -----------
- {2,1,3,4}
- (1 row)
- select array_agg(distinct a)
- from (values (1),(2),(1),(3),(null),(2)) v(a);
- array_agg
- --------------
- {1,2,3,NULL}
- (1 row)
- select array_agg(distinct a order by a)
- from (values (1),(2),(1),(3),(null),(2)) v(a);
- array_agg
- --------------
- {1,2,3,NULL}
- (1 row)
- select array_agg(distinct a order by a desc)
- from (values (1),(2),(1),(3),(null),(2)) v(a);
- array_agg
- --------------
- {NULL,3,2,1}
- (1 row)
- select array_agg(distinct a order by a desc nulls last)
- from (values (1),(2),(1),(3),(null),(2)) v(a);
- array_agg
- --------------
- {3,2,1,NULL}
- (1 row)
- -- multi-arg aggs, strict/nonstrict, distinct/order by
- select aggfstr(a,b,c)
- from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c);
- aggfstr
- ---------------------------------------
- {"(1,3,foo)","(2,2,bar)","(3,1,baz)"}
- (1 row)
- select aggfns(a,b,c)
- from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c);
- aggfns
- -----------------------------------------------
- {"(1,3,foo)","(0,,)","(2,2,bar)","(3,1,baz)"}
- (1 row)
- select aggfstr(distinct a,b,c)
- from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c),
- generate_series(1,3) i;
- aggfstr
- ---------------------------------------
- {"(1,3,foo)","(2,2,bar)","(3,1,baz)"}
- (1 row)
- select aggfns(distinct a,b,c)
- from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c),
- generate_series(1,3) i;
- aggfns
- -----------------------------------------------
- {"(0,,)","(1,3,foo)","(2,2,bar)","(3,1,baz)"}
- (1 row)
- select aggfstr(distinct a,b,c order by b)
- from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c),
- generate_series(1,3) i;
- aggfstr
- ---------------------------------------
- {"(3,1,baz)","(2,2,bar)","(1,3,foo)"}
- (1 row)
- select aggfns(distinct a,b,c order by b)
- from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c),
- generate_series(1,3) i;
- aggfns
- -----------------------------------------------
- {"(3,1,baz)","(2,2,bar)","(1,3,foo)","(0,,)"}
- (1 row)
- -- test specific code paths
- select aggfns(distinct a,a,c order by c using ~<~,a)
- from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c),
- generate_series(1,2) i;
- aggfns
- ------------------------------------------------
- {"(2,2,bar)","(3,3,baz)","(1,1,foo)","(0,0,)"}
- (1 row)
- select aggfns(distinct a,a,c order by c using ~<~)
- from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c),
- generate_series(1,2) i;
- aggfns
- ------------------------------------------------
- {"(2,2,bar)","(3,3,baz)","(1,1,foo)","(0,0,)"}
- (1 row)
- select aggfns(distinct a,a,c order by a)
- from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c),
- generate_series(1,2) i;
- aggfns
- ------------------------------------------------
- {"(0,0,)","(1,1,foo)","(2,2,bar)","(3,3,baz)"}
- (1 row)
- select aggfns(distinct a,b,c order by a,c using ~<~,b)
- from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c),
- generate_series(1,2) i;
- aggfns
- -----------------------------------------------
- {"(0,,)","(1,3,foo)","(2,2,bar)","(3,1,baz)"}
- (1 row)
- -- check node I/O via view creation and usage, also deparsing logic
- create view agg_view1 as
- select aggfns(a,b,c)
- from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c);
- select * from agg_view1;
- aggfns
- -----------------------------------------------
- {"(1,3,foo)","(0,,)","(2,2,bar)","(3,1,baz)"}
- (1 row)
- select pg_get_viewdef('agg_view1'::regclass);
- pg_get_viewdef
- ---------------------------------------------------------------------------------------------------------------------
- SELECT aggfns(v.a, v.b, v.c) AS aggfns +
- FROM ( VALUES (1,3,'foo'::text), (0,NULL::integer,NULL::text), (2,2,'bar'::text), (3,1,'baz'::text)) v(a, b, c);
- (1 row)
- create or replace view agg_view1 as
- select aggfns(distinct a,b,c)
- from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c),
- generate_series(1,3) i;
- select * from agg_view1;
- aggfns
- -----------------------------------------------
- {"(0,,)","(1,3,foo)","(2,2,bar)","(3,1,baz)"}
- (1 row)
- select pg_get_viewdef('agg_view1'::regclass);
- pg_get_viewdef
- ---------------------------------------------------------------------------------------------------------------------
- SELECT aggfns(DISTINCT v.a, v.b, v.c) AS aggfns +
- FROM ( VALUES (1,3,'foo'::text), (0,NULL::integer,NULL::text), (2,2,'bar'::text), (3,1,'baz'::text)) v(a, b, c),+
- generate_series(1, 3) i(i);
- (1 row)
- create or replace view agg_view1 as
- select aggfns(distinct a,b,c order by b)
- from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c),
- generate_series(1,3) i;
- select * from agg_view1;
- aggfns
- -----------------------------------------------
- {"(3,1,baz)","(2,2,bar)","(1,3,foo)","(0,,)"}
- (1 row)
- select pg_get_viewdef('agg_view1'::regclass);
- pg_get_viewdef
- ---------------------------------------------------------------------------------------------------------------------
- SELECT aggfns(DISTINCT v.a, v.b, v.c ORDER BY v.b) AS aggfns +
- FROM ( VALUES (1,3,'foo'::text), (0,NULL::integer,NULL::text), (2,2,'bar'::text), (3,1,'baz'::text)) v(a, b, c),+
- generate_series(1, 3) i(i);
- (1 row)
- create or replace view agg_view1 as
- select aggfns(a,b,c order by b+1)
- from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c);
- select * from agg_view1;
- aggfns
- -----------------------------------------------
- {"(3,1,baz)","(2,2,bar)","(1,3,foo)","(0,,)"}
- (1 row)
- select pg_get_viewdef('agg_view1'::regclass);
- pg_get_viewdef
- ---------------------------------------------------------------------------------------------------------------------
- SELECT aggfns(v.a, v.b, v.c ORDER BY (v.b + 1)) AS aggfns +
- FROM ( VALUES (1,3,'foo'::text), (0,NULL::integer,NULL::text), (2,2,'bar'::text), (3,1,'baz'::text)) v(a, b, c);
- (1 row)
- create or replace view agg_view1 as
- select aggfns(a,a,c order by b)
- from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c);
- select * from agg_view1;
- aggfns
- ------------------------------------------------
- {"(3,3,baz)","(2,2,bar)","(1,1,foo)","(0,0,)"}
- (1 row)
- select pg_get_viewdef('agg_view1'::regclass);
- pg_get_viewdef
- ---------------------------------------------------------------------------------------------------------------------
- SELECT aggfns(v.a, v.a, v.c ORDER BY v.b) AS aggfns +
- FROM ( VALUES (1,3,'foo'::text), (0,NULL::integer,NULL::text), (2,2,'bar'::text), (3,1,'baz'::text)) v(a, b, c);
- (1 row)
- create or replace view agg_view1 as
- select aggfns(a,b,c order by c using ~<~)
- from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c);
- select * from agg_view1;
- aggfns
- -----------------------------------------------
- {"(2,2,bar)","(3,1,baz)","(1,3,foo)","(0,,)"}
- (1 row)
- select pg_get_viewdef('agg_view1'::regclass);
- pg_get_viewdef
- ---------------------------------------------------------------------------------------------------------------------
- SELECT aggfns(v.a, v.b, v.c ORDER BY v.c USING ~<~ NULLS LAST) AS aggfns +
- FROM ( VALUES (1,3,'foo'::text), (0,NULL::integer,NULL::text), (2,2,'bar'::text), (3,1,'baz'::text)) v(a, b, c);
- (1 row)
- create or replace view agg_view1 as
- select aggfns(distinct a,b,c order by a,c using ~<~,b)
- from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c),
- generate_series(1,2) i;
- select * from agg_view1;
- aggfns
- -----------------------------------------------
- {"(0,,)","(1,3,foo)","(2,2,bar)","(3,1,baz)"}
- (1 row)
- select pg_get_viewdef('agg_view1'::regclass);
- pg_get_viewdef
- ---------------------------------------------------------------------------------------------------------------------
- SELECT aggfns(DISTINCT v.a, v.b, v.c ORDER BY v.a, v.c USING ~<~ NULLS LAST, v.b) AS aggfns +
- FROM ( VALUES (1,3,'foo'::text), (0,NULL::integer,NULL::text), (2,2,'bar'::text), (3,1,'baz'::text)) v(a, b, c),+
- generate_series(1, 2) i(i);
- (1 row)
- drop view agg_view1;
- -- incorrect DISTINCT usage errors
- select aggfns(distinct a,b,c order by i)
- from (values (1,1,'foo')) v(a,b,c), generate_series(1,2) i;
- ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list
- LINE 1: select aggfns(distinct a,b,c order by i)
- ^
- select aggfns(distinct a,b,c order by a,b+1)
- from (values (1,1,'foo')) v(a,b,c), generate_series(1,2) i;
- ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list
- LINE 1: select aggfns(distinct a,b,c order by a,b+1)
- ^
- select aggfns(distinct a,b,c order by a,b,i,c)
- from (values (1,1,'foo')) v(a,b,c), generate_series(1,2) i;
- ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list
- LINE 1: select aggfns(distinct a,b,c order by a,b,i,c)
- ^
- select aggfns(distinct a,a,c order by a,b)
- from (values (1,1,'foo')) v(a,b,c), generate_series(1,2) i;
- ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list
- LINE 1: select aggfns(distinct a,a,c order by a,b)
- ^
- -- string_agg tests
- select string_agg(a,',') from (values('aaaa'),('bbbb'),('cccc')) g(a);
- string_agg
- ----------------
- aaaa,bbbb,cccc
- (1 row)
- select string_agg(a,',') from (values('aaaa'),(null),('bbbb'),('cccc')) g(a);
- string_agg
- ----------------
- aaaa,bbbb,cccc
- (1 row)
- select string_agg(a,'AB') from (values(null),(null),('bbbb'),('cccc')) g(a);
- string_agg
- ------------
- bbbbABcccc
- (1 row)
- select string_agg(a,',') from (values(null),(null)) g(a);
- string_agg
- ------------
-
- (1 row)
- -- check some implicit casting cases, as per bug #5564
- select string_agg(distinct f1, ',' order by f1) from varchar_tbl; -- ok
- string_agg
- ------------
- a,ab,abcd
- (1 row)
- select string_agg(distinct f1::text, ',' order by f1) from varchar_tbl; -- not ok
- ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list
- LINE 1: select string_agg(distinct f1::text, ',' order by f1) from v...
- ^
- select string_agg(distinct f1, ',' order by f1::text) from varchar_tbl; -- not ok
- ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list
- LINE 1: select string_agg(distinct f1, ',' order by f1::text) from v...
- ^
- select string_agg(distinct f1::text, ',' order by f1::text) from varchar_tbl; -- ok
- string_agg
- ------------
- a,ab,abcd
- (1 row)
- -- string_agg bytea tests
- create table bytea_test_table(v bytea);
- select string_agg(v, '') from bytea_test_table;
- string_agg
- ------------
-
- (1 row)
- insert into bytea_test_table values(decode('ff','hex'));
- select string_agg(v, '') from bytea_test_table;
- string_agg
- ------------
- \xff
- (1 row)
- insert into bytea_test_table values(decode('aa','hex'));
- select string_agg(v, '') from bytea_test_table;
- string_agg
- ------------
- \xffaa
- (1 row)
- select string_agg(v, NULL) from bytea_test_table;
- string_agg
- ------------
- \xffaa
- (1 row)
- select string_agg(v, decode('ee', 'hex')) from bytea_test_table;
- string_agg
- ------------
- \xffeeaa
- (1 row)
- drop table bytea_test_table;
- -- FILTER tests
- select min(unique1) filter (where unique1 > 100) from tenk1;
- min
- -----
- 101
- (1 row)
- select sum(1/ten) filter (where ten > 0) from tenk1;
- sum
- ------
- 1000
- (1 row)
- select ten, sum(distinct four) filter (where four::text ~ '123') from onek a
- group by ten;
- ten | sum
- -----+-----
- 0 |
- 1 |
- 2 |
- 3 |
- 4 |
- 5 |
- 6 |
- 7 |
- 8 |
- 9 |
- (10 rows)
- select ten, sum(distinct four) filter (where four > 10) from onek a
- group by ten
- having exists (select 1 from onek b where sum(distinct a.four) = b.four);
- ten | sum
- -----+-----
- 0 |
- 2 |
- 4 |
- 6 |
- 8 |
- (5 rows)
- select max(foo COLLATE "C") filter (where (bar collate "POSIX") > '0')
- from (values ('a', 'b')) AS v(foo,bar);
- max
- -----
- a
- (1 row)
- -- outer reference in FILTER (PostgreSQL extension)
- select (select count(*)
- from (values (1)) t0(inner_c))
- from (values (2),(3)) t1(outer_c); -- inner query is aggregation query
- count
- -------
- 1
- 1
- (2 rows)
- select (select count(*) filter (where outer_c <> 0)
- from (values (1)) t0(inner_c))
- from (values (2),(3)) t1(outer_c); -- outer query is aggregation query
- count
- -------
- 2
- (1 row)
- select (select count(inner_c) filter (where outer_c <> 0)
- from (values (1)) t0(inner_c))
- from (values (2),(3)) t1(outer_c); -- inner query is aggregation query
- count
- -------
- 1
- 1
- (2 rows)
- select
- (select max((select i.unique2 from tenk1 i where i.unique1 = o.unique1))
- filter (where o.unique1 < 10))
- from tenk1 o; -- outer query is aggregation query
- max
- ------
- 9998
- (1 row)
- -- subquery in FILTER clause (PostgreSQL extension)
- select sum(unique1) FILTER (WHERE
- unique1 IN (SELECT unique1 FROM onek where unique1 < 100)) FROM tenk1;
- sum
- ------
- 4950
- (1 row)
- -- exercise lots of aggregate parts with FILTER
- select aggfns(distinct a,b,c order by a,c using ~<~,b) filter (where a > 1)
- from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c),
- generate_series(1,2) i;
- aggfns
- ---------------------------
- {"(2,2,bar)","(3,1,baz)"}
- (1 row)
- -- check handling of bare boolean Var in FILTER
- select max(0) filter (where b1) from bool_test;
- max
- -----
- 0
- (1 row)
- select (select max(0) filter (where b1)) from bool_test;
- max
- -----
- 0
- (1 row)
- -- check for correct detection of nested-aggregate errors in FILTER
- select max(unique1) filter (where sum(ten) > 0) from tenk1;
- ERROR: aggregate functions are not allowed in FILTER
- LINE 1: select max(unique1) filter (where sum(ten) > 0) from tenk1;
- ^
- select (select max(unique1) filter (where sum(ten) > 0) from int8_tbl) from tenk1;
- ERROR: aggregate function calls cannot be nested
- LINE 1: select (select max(unique1) filter (where sum(ten) > 0) from...
- ^
- select max(unique1) filter (where bool_or(ten > 0)) from tenk1;
- ERROR: aggregate functions are not allowed in FILTER
- LINE 1: select max(unique1) filter (where bool_or(ten > 0)) from ten...
- ^
- select (select max(unique1) filter (where bool_or(ten > 0)) from int8_tbl) from tenk1;
- ERROR: aggregate function calls cannot be nested
- LINE 1: select (select max(unique1) filter (where bool_or(ten > 0)) ...
- ^
- -- ordered-set aggregates
- select p, percentile_cont(p) within group (order by x::float8)
- from generate_series(1,5) x,
- (values (0::float8),(0.1),(0.25),(0.4),(0.5),(0.6),(0.75),(0.9),(1)) v(p)
- group by p order by p;
- p | percentile_cont
- ------+-----------------
- 0 | 1
- 0.1 | 1.4
- 0.25 | 2
- 0.4 | 2.6
- 0.5 | 3
- 0.6 | 3.4
- 0.75 | 4
- 0.9 | 4.6
- 1 | 5
- (9 rows)
- select p, percentile_cont(p order by p) within group (order by x) -- error
- from generate_series(1,5) x,
- (values (0::float8),(0.1),(0.25),(0.4),(0.5),(0.6),(0.75),(0.9),(1)) v(p)
- group by p order by p;
- ERROR: cannot use multiple ORDER BY clauses with WITHIN GROUP
- LINE 1: select p, percentile_cont(p order by p) within group (order ...
- ^
- select p, sum() within group (order by x::float8) -- error
- from generate_series(1,5) x,
- (values (0::float8),(0.1),(0.25),(0.4),(0.5),(0.6),(0.75),(0.9),(1)) v(p)
- group by p order by p;
- ERROR: sum is not an ordered-set aggregate, so it cannot have WITHIN GROUP
- LINE 1: select p, sum() within group (order by x::float8)
- ^
- select p, percentile_cont(p,p) -- error
- from generate_series(1,5) x,
- (values (0::float8),(0.1),(0.25),(0.4),(0.5),(0.6),(0.75),(0.9),(1)) v(p)
- group by p order by p;
- ERROR: WITHIN GROUP is required for ordered-set aggregate percentile_cont
- LINE 1: select p, percentile_cont(p,p)
- ^
- select percentile_cont(0.5) within group (order by b) from aggtest;
- percentile_cont
- ------------------
- 53.4485001564026
- (1 row)
- select percentile_cont(0.5) within group (order by b), sum(b) from aggtest;
- percentile_cont | sum
- ------------------+---------
- 53.4485001564026 | 431.773
- (1 row)
- select percentile_cont(0.5) within group (order by thousand) from tenk1;
- percentile_cont
- -----------------
- 499.5
- (1 row)
- select percentile_disc(0.5) within group (order by thousand) from tenk1;
- percentile_disc
- -----------------
- 499
- (1 row)
- select rank(3) within group (order by x)
- from (values (1),(1),(2),(2),(3),(3),(4)) v(x);
- rank
- ------
- 5
- (1 row)
- select cume_dist(3) within group (order by x)
- from (values (1),(1),(2),(2),(3),(3),(4)) v(x);
- cume_dist
- -----------
- 0.875
- (1 row)
- select percent_rank(3) within group (order by x)
- from (values (1),(1),(2),(2),(3),(3),(4),(5)) v(x);
- percent_rank
- --------------
- 0.5
- (1 row)
- select dense_rank(3) within group (order by x)
- from (values (1),(1),(2),(2),(3),(3),(4)) v(x);
- dense_rank
- ------------
- 3
- (1 row)
- select percentile_disc(array[0,0.1,0.25,0.5,0.75,0.9,1]) within group (order by thousand)
- from tenk1;
- percentile_disc
- ----------------------------
- {0,99,249,499,749,899,999}
- (1 row)
- select percentile_cont(array[0,0.25,0.5,0.75,1]) within group (order by thousand)
- from tenk1;
- percentile_cont
- -----------------------------
- {0,249.75,499.5,749.25,999}
- (1 row)
- select percentile_disc(array[[null,1,0.5],[0.75,0.25,null]]) within group (order by thousand)
- from tenk1;
- percentile_disc
- ---------------------------------
- {{NULL,999,499},{749,249,NULL}}
- (1 row)
- select percentile_cont(array[0,1,0.25,0.75,0.5,1,0.3,0.32,0.35,0.38,0.4]) within group (order by x)
- from generate_series(1,6) x;
- percentile_cont
- ------------------------------------------
- {1,6,2.25,4.75,3.5,6,2.5,2.6,2.75,2.9,3}
- (1 row)
- select ten, mode() within group (order by string4) from tenk1 group by ten;
- ten | mode
- -----+--------
- 0 | HHHHxx
- 1 | OOOOxx
- 2 | VVVVxx
- 3 | OOOOxx
- 4 | HHHHxx
- 5 | HHHHxx
- 6 | OOOOxx
- 7 | AAAAxx
- 8 | VVVVxx
- 9 | VVVVxx
- (10 rows)
- select percentile_disc(array[0.25,0.5,0.75]) within group (order by x)
- from unnest('{fred,jim,fred,jack,jill,fred,jill,jim,jim,sheila,jim,sheila}'::text[]) u(x);
- percentile_disc
- -----------------
- {fred,jill,jim}
- (1 row)
- -- check collation propagates up in suitable cases:
- select pg_collation_for(percentile_disc(1) within group (order by x collate "POSIX"))
- from (values ('fred'),('jim')) v(x);
- pg_collation_for
- ------------------
- "POSIX"
- (1 row)
- -- ordered-set aggs created with CREATE AGGREGATE
- select test_rank(3) within group (order by x)
- from (values (1),(1),(2),(2),(3),(3),(4)) v(x);
- test_rank
- -----------
- 5
- (1 row)
- select test_percentile_disc(0.5) within group (order by thousand) from tenk1;
- test_percentile_disc
- ----------------------
- 499
- (1 row)
- -- ordered-set aggs can't use ungrouped vars in direct args:
- select rank(x) within group (order by x) from generate_series(1,5) x;
- ERROR: column "x.x" must appear in the GROUP BY clause or be used in an aggregate function
- LINE 1: select rank(x) within group (order by x) from generate_serie...
- ^
- DETAIL: Direct arguments of an ordered-set aggregate must use only grouped columns.
- -- outer-level agg can't use a grouped arg of a lower level, either:
- select array(select percentile_disc(a) within group (order by x)
- from (values (0.3),(0.7)) v(a) group by a)
- from generate_series(1,5) g(x);
- ERROR: outer-level aggregate cannot contain a lower-level variable in its direct arguments
- LINE 1: select array(select percentile_disc(a) within group (order b...
- ^
- -- agg in the direct args is a grouping violation, too:
- select rank(sum(x)) within group (order by x) from generate_series(1,5) x;
- ERROR: aggregate function calls cannot be nested
- LINE 1: select rank(sum(x)) within group (order by x) from generate_...
- ^
- -- hypothetical-set type unification and argument-count failures:
- select rank(3) within group (order by x) from (values ('fred'),('jim')) v(x);
- ERROR: WITHIN GROUP types text and integer cannot be matched
- LINE 1: select rank(3) within group (order by x) from (values ('fred...
- ^
- select rank(3) within group (order by stringu1,stringu2) from tenk1;
- ERROR: function rank(integer, name, name) does not exist
- LINE 1: select rank(3) within group (order by stringu1,stringu2) fro...
- ^
- HINT: To use the hypothetical-set aggregate rank, the number of hypothetical direct arguments (here 1) must match the number of ordering columns (here 2).
- select rank('fred') within group (order by x) from generate_series(1,5) x;
- ERROR: invalid input syntax for type integer: "fred"
- LINE 1: select rank('fred') within group (order by x) from generate_...
- ^
- select rank('adam'::text collate "C") within group (order by x collate "POSIX")
- from (values ('fred'),('jim')) v(x);
- ERROR: collation mismatch between explicit collations "C" and "POSIX"
- LINE 1: ...adam'::text collate "C") within group (order by x collate "P...
- ^
- -- hypothetical-set type unification successes:
- select rank('adam'::varchar) within group (order by x) from (values ('fred'),('jim')) v(x);
- rank
- ------
- 1
- (1 row)
- select rank('3') within group (order by x) from generate_series(1,5) x;
- rank
- ------
- 3
- (1 row)
- -- divide by zero check
- select percent_rank(0) within group (order by x) from generate_series(1,0) x;
- percent_rank
- --------------
- 0
- (1 row)
- -- deparse and multiple features:
- create view aggordview1 as
- select ten,
- percentile_disc(0.5) within group (order by thousand) as p50,
- percentile_disc(0.5) within group (order by thousand) filter (where hundred=1) as px,
- rank(5,'AZZZZ',50) within group (order by hundred, string4 desc, hundred)
- from tenk1
- group by ten order by ten;
- select pg_get_viewdef('aggordview1');
- pg_get_viewdef
- -------------------------------------------------------------------------------------------------------------------------------
- SELECT tenk1.ten, +
- percentile_disc((0.5)::double precision) WITHIN GROUP (ORDER BY tenk1.thousand) AS p50, +
- percentile_disc((0.5)::double precision) WITHIN GROUP (ORDER BY tenk1.thousand) FILTER (WHERE (tenk1.hundred = 1)) AS px,+
- rank(5, 'AZZZZ'::name, 50) WITHIN GROUP (ORDER BY tenk1.hundred, tenk1.string4 DESC, tenk1.hundred) AS rank +
- FROM tenk1 +
- GROUP BY tenk1.ten +
- ORDER BY tenk1.ten;
- (1 row)
- select * from aggordview1 order by ten;
- ten | p50 | px | rank
- -----+-----+-----+------
- 0 | 490 | | 101
- 1 | 491 | 401 | 101
- 2 | 492 | | 101
- 3 | 493 | | 101
- 4 | 494 | | 101
- 5 | 495 | | 67
- 6 | 496 | | 1
- 7 | 497 | | 1
- 8 | 498 | | 1
- 9 | 499 | | 1
- (10 rows)
- drop view aggordview1;
- -- variadic aggregates
- select least_agg(q1,q2) from int8_tbl;
- least_agg
- -------------------
- -4567890123456789
- (1 row)
- select least_agg(variadic array[q1,q2]) from int8_tbl;
- least_agg
- -------------------
- -4567890123456789
- (1 row)
- select cleast_agg(q1,q2) from int8_tbl;
- cleast_agg
- -------------------
- -4567890123456789
- (1 row)
- select cleast_agg(4.5,f1) from int4_tbl;
- cleast_agg
- -------------
- -2147483647
- (1 row)
- select cleast_agg(variadic array[4.5,f1]) from int4_tbl;
- cleast_agg
- -------------
- -2147483647
- (1 row)
- select pg_typeof(cleast_agg(variadic array[4.5,f1])) from int4_tbl;
- pg_typeof
- -----------
- numeric
- (1 row)
- -- test aggregates with common transition functions share the same states
- begin work;
- create type avg_state as (total bigint, count bigint);
- create or replace function avg_transfn(state avg_state, n int) returns avg_state as
- $$
- declare new_state avg_state;
- begin
- raise notice 'avg_transfn called with %', n;
- if state is null then
- if n is not null then
- new_state.total := n;
- new_state.count := 1;
- return new_state;
- end if;
- return null;
- elsif n is not null then
- state.total := state.total + n;
- state.count := state.count + 1;
- return state;
- end if;
- return null;
- end
- $$ language plpgsql;
- create function avg_finalfn(state avg_state) returns int4 as
- $$
- begin
- if state is null then
- return NULL;
- else
- return state.total / state.count;
- end if;
- end
- $$ language plpgsql;
- create function sum_finalfn(state avg_state) returns int4 as
- $$
- begin
- if state is null then
- return NULL;
- else
- return state.total;
- end if;
- end
- $$ language plpgsql;
- create aggregate my_avg(int4)
- (
- stype = avg_state,
- sfunc = avg_transfn,
- finalfunc = avg_finalfn
- );
- create aggregate my_sum(int4)
- (
- stype = avg_state,
- sfunc = avg_transfn,
- finalfunc = sum_finalfn
- );
- -- aggregate state should be shared as aggs are the same.
- select my_avg(one),my_avg(one) from (values(1),(3)) t(one);
- NOTICE: avg_transfn called with 1
- NOTICE: avg_transfn called with 3
- my_avg | my_avg
- --------+--------
- 2 | 2
- (1 row)
- -- aggregate state should be shared as transfn is the same for both aggs.
- select my_avg(one),my_sum(one) from (values(1),(3)) t(one);
- NOTICE: avg_transfn called with 1
- NOTICE: avg_transfn called with 3
- my_avg | my_sum
- --------+--------
- 2 | 4
- (1 row)
- -- same as previous one, but with DISTINCT, which requires sorting the input.
- select my_avg(distinct one),my_sum(distinct one) from (values(1),(3),(1)) t(one);
- NOTICE: avg_transfn called with 1
- NOTICE: avg_transfn called with 3
- my_avg | my_sum
- --------+--------
- 2 | 4
- (1 row)
- -- shouldn't share states due to the distinctness not matching.
- select my_avg(distinct one),my_sum(one) from (values(1),(3)) t(one);
- NOTICE: avg_transfn called with 1
- NOTICE: avg_transfn called with 3
- NOTICE: avg_transfn called with 1
- NOTICE: avg_transfn called with 3
- my_avg | my_sum
- --------+--------
- 2 | 4
- (1 row)
- -- shouldn't share states due to the filter clause not matching.
- select my_avg(one) filter (where one > 1),my_sum(one) from (values(1),(3)) t(one);
- NOTICE: avg_transfn called with 1
- NOTICE: avg_transfn called with 3
- NOTICE: avg_transfn called with 3
- my_avg | my_sum
- --------+--------
- 3 | 4
- (1 row)
- -- this should not share the state due to different input columns.
- select my_avg(one),my_sum(two) from (values(1,2),(3,4)) t(one,two);
- NOTICE: avg_transfn called with 1
- NOTICE: avg_transfn called with 2
- NOTICE: avg_transfn called with 3
- NOTICE: avg_transfn called with 4
- my_avg | my_sum
- --------+--------
- 2 | 6
- (1 row)
- -- exercise cases where OSAs share state
- select
- percentile_cont(0.5) within group (order by a),
- percentile_disc(0.5) within group (order by a)
- from (values(1::float8),(3),(5),(7)) t(a);
- percentile_cont | percentile_disc
- -----------------+-----------------
- 4 | 3
- (1 row)
- select
- percentile_cont(0.25) within group (order by a),
- percentile_disc(0.5) within group (order by a)
- from (values(1::float8),(3),(5),(7)) t(a);
- percentile_cont | percentile_disc
- -----------------+-----------------
- 2.5 | 3
- (1 row)
- -- these can't share state currently
- select
- rank(4) within group (order by a),
- dense_rank(4) within group (order by a)
- from (values(1),(3),(5),(7)) t(a);
- rank | dense_rank
- ------+------------
- 3 | 3
- (1 row)
- -- test that aggs with the same sfunc and initcond share the same agg state
- create aggregate my_sum_init(int4)
- (
- stype = avg_state,
- sfunc = avg_transfn,
- finalfunc = sum_finalfn,
- initcond = '(10,0)'
- );
- create aggregate my_avg_init(int4)
- (
- stype = avg_state,
- sfunc = avg_transfn,
- finalfunc = avg_finalfn,
- initcond = '(10,0)'
- );
- create aggregate my_avg_init2(int4)
- (
- stype = avg_state,
- sfunc = avg_transfn,
- finalfunc = avg_finalfn,
- initcond = '(4,0)'
- );
- -- state should be shared if INITCONDs are matching
- select my_sum_init(one),my_avg_init(one) from (values(1),(3)) t(one);
- NOTICE: avg_transfn called with 1
- NOTICE: avg_transfn called with 3
- my_sum_init | my_avg_init
- -------------+-------------
- 14 | 7
- (1 row)
- -- Varying INITCONDs should cause the states not to be shared.
- select my_sum_init(one),my_avg_init2(one) from (values(1),(3)) t(one);
- NOTICE: avg_transfn called with 1
- NOTICE: avg_transfn called with 1
- NOTICE: avg_transfn called with 3
- NOTICE: avg_transfn called with 3
- my_sum_init | my_avg_init2
- -------------+--------------
- 14 | 4
- (1 row)
- rollback;
- -- test aggregate state sharing to ensure it works if one aggregate has a
- -- finalfn and the other one has none.
- begin work;
- create or replace function sum_transfn(state int4, n int4) returns int4 as
- $$
- declare new_state int4;
- begin
- raise notice 'sum_transfn called with %', n;
- if state is null then
- if n is not null then
- new_state := n;
- return new_state;
- end if;
- return null;
- elsif n is not null then
- state := state + n;
- return state;
- end if;
- return null;
- end
- $$ language plpgsql;
- create function halfsum_finalfn(state int4) returns int4 as
- $$
- begin
- if state is null then
- return NULL;
- else
- return state / 2;
- end if;
- end
- $$ language plpgsql;
- create aggregate my_sum(int4)
- (
- stype = int4,
- sfunc = sum_transfn
- );
- create aggregate my_half_sum(int4)
- (
- stype = int4,
- sfunc = sum_transfn,
- finalfunc = halfsum_finalfn
- );
- -- Agg state should be shared even though my_sum has no finalfn
- select my_sum(one),my_half_sum(one) from (values(1),(2),(3),(4)) t(one);
- NOTICE: sum_transfn called with 1
- NOTICE: sum_transfn called with 2
- NOTICE: sum_transfn called with 3
- NOTICE: sum_transfn called with 4
- my_sum | my_half_sum
- --------+-------------
- 10 | 5
- (1 row)
- rollback;
- -- test that the aggregate transition logic correctly handles
- -- transition / combine functions returning NULL
- -- First test the case of a normal transition function returning NULL
- BEGIN;
- CREATE FUNCTION balkifnull(int8, int4)
- RETURNS int8
- STRICT
- LANGUAGE plpgsql AS $$
- BEGIN
- IF $1 IS NULL THEN
- RAISE 'erroneously called with NULL argument';
- END IF;
- RETURN NULL;
- END$$;
- CREATE AGGREGATE balk(int4)
- (
- SFUNC = balkifnull(int8, int4),
- STYPE = int8,
- PARALLEL = SAFE,
- INITCOND = '0'
- );
- SELECT balk(hundred) FROM tenk1;
- balk
- ------
-
- (1 row)
- ROLLBACK;
- -- Secondly test the case of a parallel aggregate combiner function
- -- returning NULL. For that use normal transition function, but a
- -- combiner function returning NULL.
- BEGIN;
- CREATE FUNCTION balkifnull(int8, int8)
- RETURNS int8
- PARALLEL SAFE
- STRICT
- LANGUAGE plpgsql AS $$
- BEGIN
- IF $1 IS NULL THEN
- RAISE 'erroneously called with NULL argument';
- END IF;
- RETURN NULL;
- END$$;
- CREATE AGGREGATE balk(int4)
- (
- SFUNC = int4_sum(int8, int4),
- STYPE = int8,
- COMBINEFUNC = balkifnull(int8, int8),
- PARALLEL = SAFE,
- INITCOND = '0'
- );
- -- force use of parallelism
- ALTER TABLE tenk1 set (parallel_workers = 4);
- SET LOCAL parallel_setup_cost=0;
- SET LOCAL max_parallel_workers_per_gather=4;
- EXPLAIN (COSTS OFF) SELECT balk(hundred) FROM tenk1;
- QUERY PLAN
- -------------------------------------------------------------------------
- Finalize Aggregate
- -> Gather
- Workers Planned: 4
- -> Partial Aggregate
- -> Parallel Index Only Scan using tenk1_hundred on tenk1
- (5 rows)
- SELECT balk(hundred) FROM tenk1;
- balk
- ------
-
- (1 row)
- ROLLBACK;
- -- test coverage for aggregate combine/serial/deserial functions
- BEGIN;
- SET parallel_setup_cost = 0;
- SET parallel_tuple_cost = 0;
- SET min_parallel_table_scan_size = 0;
- SET max_parallel_workers_per_gather = 4;
- SET parallel_leader_participation = off;
- SET enable_indexonlyscan = off;
- -- variance(int4) covers numeric_poly_combine
- -- sum(int8) covers int8_avg_combine
- -- regr_count(float8, float8) covers int8inc_float8_float8 and aggregates with > 1 arg
- EXPLAIN (COSTS OFF, VERBOSE)
- SELECT variance(unique1::int4), sum(unique1::int8), regr_count(unique1::float8, unique1::float8)
- FROM (SELECT * FROM tenk1
- UNION ALL SELECT * FROM tenk1
- UNION ALL SELECT * FROM tenk1
- UNION ALL SELECT * FROM tenk1) u;
- QUERY PLAN
- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
- Finalize Aggregate
- Output: variance(tenk1.unique1), sum((tenk1.unique1)::bigint), regr_count((tenk1.unique1)::double precision, (tenk1.unique1)::double precision)
- -> Gather
- Output: (PARTIAL variance(tenk1.unique1)), (PARTIAL sum((tenk1.unique1)::bigint)), (PARTIAL regr_count((tenk1.unique1)::double precision, (tenk1.unique1)::double precision))
- Workers Planned: 4
- -> Partial Aggregate
- Output: PARTIAL variance(tenk1.unique1), PARTIAL sum((tenk1.unique1)::bigint), PARTIAL regr_count((tenk1.unique1)::double precision, (tenk1.unique1)::double precision)
- -> Parallel Append
- -> Parallel Seq Scan on public.tenk1
- Output: tenk1.unique1
- -> Parallel Seq Scan on public.tenk1 tenk1_1
- Output: tenk1_1.unique1
- -> Parallel Seq Scan on public.tenk1 tenk1_2
- Output: tenk1_2.unique1
- -> Parallel Seq Scan on public.tenk1 tenk1_3
- Output: tenk1_3.unique1
- (16 rows)
- SELECT variance(unique1::int4), sum(unique1::int8), regr_count(unique1::float8, unique1::float8)
- FROM (SELECT * FROM tenk1
- UNION ALL SELECT * FROM tenk1
- UNION ALL SELECT * FROM tenk1
- UNION ALL SELECT * FROM tenk1) u;
- variance | sum | regr_count
- ----------------------+-----------+------------
- 8333541.588539713493 | 199980000 | 40000
- (1 row)
- -- variance(int8) covers numeric_combine
- -- avg(numeric) covers numeric_avg_combine
- EXPLAIN (COSTS OFF, VERBOSE)
- SELECT variance(unique1::int8), avg(unique1::numeric)
- FROM (SELECT * FROM tenk1
- UNION ALL SELECT * FROM tenk1
- UNION ALL SELECT * FROM tenk1
- UNION ALL SELECT * FROM tenk1) u;
- QUERY PLAN
- --------------------------------------------------------------------------------------------------------
- Finalize Aggregate
- Output: variance((tenk1.unique1)::bigint), avg((tenk1.unique1)::numeric)
- -> Gather
- Output: (PARTIAL variance((tenk1.unique1)::bigint)), (PARTIAL avg((tenk1.unique1)::numeric))
- Workers Planned: 4
- -> Partial Aggregate
- Output: PARTIAL variance((tenk1.unique1)::bigint), PARTIAL avg((tenk1.unique1)::numeric)
- -> Parallel Append
- -> Parallel Seq Scan on public.tenk1
- Output: tenk1.unique1
- -> Parallel Seq Scan on public.tenk1 tenk1_1
- Output: tenk1_1.unique1
- -> Parallel Seq Scan on public.tenk1 tenk1_2
- Output: tenk1_2.unique1
- -> Parallel Seq Scan on public.tenk1 tenk1_3
- Output: tenk1_3.unique1
- (16 rows)
- SELECT variance(unique1::int8), avg(unique1::numeric)
- FROM (SELECT * FROM tenk1
- UNION ALL SELECT * FROM tenk1
- UNION ALL SELECT * FROM tenk1
- UNION ALL SELECT * FROM tenk1) u;
- variance | avg
- ----------------------+-----------------------
- 8333541.588539713493 | 4999.5000000000000000
- (1 row)
- ROLLBACK;
- -- test coverage for dense_rank
- SELECT dense_rank(x) WITHIN GROUP (ORDER BY x) FROM (VALUES (1),(1),(2),(2),(3),(3)) v(x) GROUP BY (x) ORDER BY 1;
- dense_rank
- ------------
- 1
- 1
- 1
- (3 rows)
- -- Ensure that the STRICT checks for aggregates does not take NULLness
- -- of ORDER BY columns into account. See bug report around
- -- 2a505161-2727-2473-7c46-591ed108ac52@email.cz
- SELECT min(x ORDER BY y) FROM (VALUES(1, NULL)) AS d(x,y);
- min
- -----
- 1
- (1 row)
- SELECT min(x ORDER BY y) FROM (VALUES(1, 2)) AS d(x,y);
- min
- -----
- 1
- (1 row)
- -- check collation-sensitive matching between grouping expressions
- select v||'a', case v||'a' when 'aa' then 1 else 0 end, count(*)
- from unnest(array['a','b']) u(v)
- group by v||'a' order by 1;
- ?column? | case | count
- ----------+------+-------
- aa | 1 | 1
- ba | 0 | 1
- (2 rows)
- select v||'a', case when v||'a' = 'aa' then 1 else 0 end, count(*)
- from unnest(array['a','b']) u(v)
- group by v||'a' order by 1;
- ?column? | case | count
- ----------+------+-------
- aa | 1 | 1
- ba | 0 | 1
- (2 rows)
- -- Make sure that generation of HashAggregate for uniqification purposes
- -- does not lead to array overflow due to unexpected duplicate hash keys
- -- see CAFeeJoKKu0u+A_A9R9316djW-YW3-+Gtgvy3ju655qRHR3jtdA@mail.gmail.com
- set enable_memoize to off;
- explain (costs off)
- select 1 from tenk1
- where (hundred, thousand) in (select twothousand, twothousand from onek);
- QUERY PLAN
- -------------------------------------------------------------
- Hash Join
- Hash Cond: (tenk1.hundred = onek.twothousand)
- -> Seq Scan on tenk1
- Filter: (hundred = thousand)
- -> Hash
- -> HashAggregate
- Group Key: onek.twothousand, onek.twothousand
- -> Seq Scan on onek
- (8 rows)
- reset enable_memoize;
- --
- -- Hash Aggregation Spill tests
- --
- set enable_sort=false;
- set work_mem='64kB';
- select unique1, count(*), sum(twothousand) from tenk1
- group by unique1
- having sum(fivethous) > 4975
- order by sum(twothousand);
- unique1 | count | sum
- ---------+-------+------
- 4976 | 1 | 976
- 4977 | 1 | 977
- 4978 | 1 | 978
- 4979 | 1 | 979
- 4980 | 1 | 980
- 4981 | 1 | 981
- 4982 | 1 | 982
- 4983 | 1 | 983
- 4984 | 1 | 984
- 4985 | 1 | 985
- 4986 | 1 | 986
- 4987 | 1 | 987
- 4988 | 1 | 988
- 4989 | 1 | 989
- 4990 | 1 | 990
- 4991 | 1 | 991
- 4992 | 1 | 992
- 4993 | 1 | 993
- 4994 | 1 | 994
- 4995 | 1 | 995
- 4996 | 1 | 996
- 4997 | 1 | 997
- 4998 | 1 | 998
- 4999 | 1 | 999
- 9976 | 1 | 1976
- 9977 | 1 | 1977
- 9978 | 1 | 1978
- 9979 | 1 | 1979
- 9980 | 1 | 1980
- 9981 | 1 | 1981
- 9982 | 1 | 1982
- 9983 | 1 | 1983
- 9984 | 1 | 1984
- 9985 | 1 | 1985
- 9986 | 1 | 1986
- 9987 | 1 | 1987
- 9988 | 1 | 1988
- 9989 | 1 | 1989
- 9990 | 1 | 1990
- 9991 | 1 | 1991
- 9992 | 1 | 1992
- 9993 | 1 | 1993
- 9994 | 1 | 1994
- 9995 | 1 | 1995
- 9996 | 1 | 1996
- 9997 | 1 | 1997
- 9998 | 1 | 1998
- 9999 | 1 | 1999
- (48 rows)
- set work_mem to default;
- set enable_sort to default;
- --
- -- Compare results between plans using sorting and plans using hash
- -- aggregation. Force spilling in both cases by setting work_mem low.
- --
- set work_mem='64kB';
- create table agg_data_2k as
- select g from generate_series(0, 1999) g;
- analyze agg_data_2k;
- create table agg_data_20k as
- select g from generate_series(0, 19999) g;
- analyze agg_data_20k;
- -- Produce results with sorting.
- set enable_hashagg = false;
- set jit_above_cost = 0;
- explain (costs off)
- select g%10000 as c1, sum(g::numeric) as c2, count(*) as c3
- from agg_data_20k group by g%10000;
- QUERY PLAN
- --------------------------------------
- GroupAggregate
- Group Key: ((g % 10000))
- -> Sort
- Sort Key: ((g % 10000))
- -> Seq Scan on agg_data_20k
- (5 rows)
- create table agg_group_1 as
- select g%10000 as c1, sum(g::numeric) as c2, count(*) as c3
- from agg_data_20k group by g%10000;
- create table agg_group_2 as
- select * from
- (values (100), (300), (500)) as r(a),
- lateral (
- select (g/2)::numeric as c1,
- array_agg(g::numeric) as c2,
- count(*) as c3
- from agg_data_2k
- where g < r.a
- group by g/2) as s;
- set jit_above_cost to default;
- create table agg_group_3 as
- select (g/2)::numeric as c1, sum(7::int4) as c2, count(*) as c3
- from agg_data_2k group by g/2;
- create table agg_group_4 as
- select (g/2)::numeric as c1, array_agg(g::numeric) as c2, count(*) as c3
- from agg_data_2k group by g/2;
- -- Produce results with hash aggregation
- set enable_hashagg = true;
- set enable_sort = false;
- set jit_above_cost = 0;
- explain (costs off)
- select g%10000 as c1, sum(g::numeric) as c2, count(*) as c3
- from agg_data_20k group by g%10000;
- QUERY PLAN
- --------------------------------
- HashAggregate
- Group Key: (g % 10000)
- -> Seq Scan on agg_data_20k
- (3 rows)
- create table agg_hash_1 as
- select g%10000 as c1, sum(g::numeric) as c2, count(*) as c3
- from agg_data_20k group by g%10000;
- create table agg_hash_2 as
- select * from
- (values (100), (300), (500)) as r(a),
- lateral (
- select (g/2)::numeric as c1,
- array_agg(g::numeric) as c2,
- count(*) as c3
- from agg_data_2k
- where g < r.a
- group by g/2) as s;
- set jit_above_cost to default;
- create table agg_hash_3 as
- select (g/2)::numeric as c1, sum(7::int4) as c2, count(*) as c3
- from agg_data_2k group by g/2;
- create table agg_hash_4 as
- select (g/2)::numeric as c1, array_agg(g::numeric) as c2, count(*) as c3
- from agg_data_2k group by g/2;
- set enable_sort = true;
- set work_mem to default;
- -- Compare group aggregation results to hash aggregation results
- (select * from agg_hash_1 except select * from agg_group_1)
- union all
- (select * from agg_group_1 except select * from agg_hash_1);
- c1 | c2 | c3
- ----+----+----
- (0 rows)
- (select * from agg_hash_2 except select * from agg_group_2)
- union all
- (select * from agg_group_2 except select * from agg_hash_2);
- a | c1 | c2 | c3
- ---+----+----+----
- (0 rows)
- (select * from agg_hash_3 except select * from agg_group_3)
- union all
- (select * from agg_group_3 except select * from agg_hash_3);
- c1 | c2 | c3
- ----+----+----
- (0 rows)
- (select * from agg_hash_4 except select * from agg_group_4)
- union all
- (select * from agg_group_4 except select * from agg_hash_4);
- c1 | c2 | c3
- ----+----+----
- (0 rows)
- drop table agg_group_1;
- drop table agg_group_2;
- drop table agg_group_3;
- drop table agg_group_4;
- drop table agg_hash_1;
- drop table agg_hash_2;
- drop table agg_hash_3;
- drop table agg_hash_4;
|