mirror of
https://github.com/postgres/postgres.git
synced 2025-07-27 12:41:57 +03:00
postgres_fdw: Perform the (ORDERED, NULL) upperrel operations remotely.
The upper-planner pathification allows FDWs to arrange to push down
different types of upper-stage operations to the remote side. This
commit teaches postgres_fdw to do it for the (ORDERED, NULL) upperrel,
which is responsible for evaluating the query's ORDER BY ordering.
Since postgres_fdw is already able to evaluate that ordering remotely
for foreign baserels and foreign joinrels (see commit aa09cd242f
et al.),
this adds support for that for foreign grouping relations.
Author: Etsuro Fujita
Reviewed-By: Antonin Houska and Jeff Janes
Discussion: https://postgr.es/m/87pnz1aby9.fsf@news-spur.riddles.org.uk
This commit is contained in:
@ -2552,18 +2552,13 @@ DROP ROLE regress_view_owner;
|
||||
-- Simple aggregates
|
||||
explain (verbose, costs off)
|
||||
select count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), sum(c1) * (random() <= 1)::int as sum2 from ft1 where c2 < 5 group by c2 order by 1, 2;
|
||||
QUERY PLAN
|
||||
------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Result
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Foreign Scan
|
||||
Output: (count(c6)), (sum(c1)), (avg(c1)), (min(c2)), (max(c1)), (stddev(c2)), ((sum(c1)) * ((random() <= '1'::double precision))::integer), c2
|
||||
-> Sort
|
||||
Output: (count(c6)), (sum(c1)), (avg(c1)), (min(c2)), (max(c1)), (stddev(c2)), c2
|
||||
Sort Key: (count(ft1.c6)), (sum(ft1.c1))
|
||||
-> Foreign Scan
|
||||
Output: (count(c6)), (sum(c1)), (avg(c1)), (min(c2)), (max(c1)), (stddev(c2)), c2
|
||||
Relations: Aggregate on (public.ft1)
|
||||
Remote SQL: SELECT count(c6), sum("C 1"), avg("C 1"), min(c2), max("C 1"), stddev(c2), c2 FROM "S 1"."T 1" WHERE ((c2 < 5)) GROUP BY 7
|
||||
(9 rows)
|
||||
Relations: Aggregate on (public.ft1)
|
||||
Remote SQL: SELECT count(c6), sum("C 1"), avg("C 1"), min(c2), max("C 1"), stddev(c2), c2 FROM "S 1"."T 1" WHERE ((c2 < 5)) GROUP BY 7 ORDER BY count(c6) ASC NULLS LAST, sum("C 1") ASC NULLS LAST
|
||||
(4 rows)
|
||||
|
||||
select count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), sum(c1) * (random() <= 1)::int as sum2 from ft1 where c2 < 5 group by c2 order by 1, 2;
|
||||
count | sum | avg | min | max | stddev | sum2
|
||||
@ -2621,16 +2616,13 @@ select sum(t1.c1), count(t2.c1) from ft1 t1 inner join ft2 t2 on (t1.c1 = t2.c1)
|
||||
-- GROUP BY clause having expressions
|
||||
explain (verbose, costs off)
|
||||
select c2/2, sum(c2) * (c2/2) from ft1 group by c2/2 order by c2/2;
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------------------------
|
||||
Sort
|
||||
QUERY PLAN
|
||||
------------------------------------------------------------------------------------------------------------------
|
||||
Foreign Scan
|
||||
Output: ((c2 / 2)), ((sum(c2) * (c2 / 2)))
|
||||
Sort Key: ((ft1.c2 / 2))
|
||||
-> Foreign Scan
|
||||
Output: ((c2 / 2)), ((sum(c2) * (c2 / 2)))
|
||||
Relations: Aggregate on (public.ft1)
|
||||
Remote SQL: SELECT (c2 / 2), (sum(c2) * (c2 / 2)) FROM "S 1"."T 1" GROUP BY 1
|
||||
(7 rows)
|
||||
Relations: Aggregate on (public.ft1)
|
||||
Remote SQL: SELECT (c2 / 2), (sum(c2) * (c2 / 2)) FROM "S 1"."T 1" GROUP BY 1 ORDER BY (c2 / 2) ASC NULLS LAST
|
||||
(4 rows)
|
||||
|
||||
select c2/2, sum(c2) * (c2/2) from ft1 group by c2/2 order by c2/2;
|
||||
?column? | ?column?
|
||||
@ -2645,18 +2637,15 @@ select c2/2, sum(c2) * (c2/2) from ft1 group by c2/2 order by c2/2;
|
||||
-- Aggregates in subquery are pushed down.
|
||||
explain (verbose, costs off)
|
||||
select count(x.a), sum(x.a) from (select c2 a, sum(c1) b from ft1 group by c2, sqrt(c1) order by 1, 2) x;
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------------------------------
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Aggregate
|
||||
Output: count(ft1.c2), sum(ft1.c2)
|
||||
-> Sort
|
||||
-> Foreign Scan
|
||||
Output: ft1.c2, (sum(ft1.c1)), (sqrt((ft1.c1)::double precision))
|
||||
Sort Key: ft1.c2, (sum(ft1.c1))
|
||||
-> Foreign Scan
|
||||
Output: ft1.c2, (sum(ft1.c1)), (sqrt((ft1.c1)::double precision))
|
||||
Relations: Aggregate on (public.ft1)
|
||||
Remote SQL: SELECT c2, sum("C 1"), sqrt("C 1") FROM "S 1"."T 1" GROUP BY 1, 3
|
||||
(9 rows)
|
||||
Relations: Aggregate on (public.ft1)
|
||||
Remote SQL: SELECT c2, sum("C 1"), sqrt("C 1") FROM "S 1"."T 1" GROUP BY 1, 3 ORDER BY c2 ASC NULLS LAST, sum("C 1") ASC NULLS LAST
|
||||
(6 rows)
|
||||
|
||||
select count(x.a), sum(x.a) from (select c2 a, sum(c1) b from ft1 group by c2, sqrt(c1) order by 1, 2) x;
|
||||
count | sum
|
||||
@ -2742,16 +2731,13 @@ select count(c2) w, c2 x, 5 y, 7.0 z from ft1 group by 2, y, 9.0::int order by 2
|
||||
-- Also, ORDER BY contains an aggregate function
|
||||
explain (verbose, costs off)
|
||||
select c2, c2 from ft1 where c2 > 6 group by 1, 2 order by sum(c1);
|
||||
QUERY PLAN
|
||||
-----------------------------------------------------------------------------------------------
|
||||
Sort
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------
|
||||
Foreign Scan
|
||||
Output: c2, c2, (sum(c1))
|
||||
Sort Key: (sum(ft1.c1))
|
||||
-> Foreign Scan
|
||||
Output: c2, c2, (sum(c1))
|
||||
Relations: Aggregate on (public.ft1)
|
||||
Remote SQL: SELECT c2, c2, sum("C 1") FROM "S 1"."T 1" WHERE ((c2 > 6)) GROUP BY 1, 2
|
||||
(7 rows)
|
||||
Relations: Aggregate on (public.ft1)
|
||||
Remote SQL: SELECT c2, c2, sum("C 1") FROM "S 1"."T 1" WHERE ((c2 > 6)) GROUP BY 1, 2 ORDER BY sum("C 1") ASC NULLS LAST
|
||||
(4 rows)
|
||||
|
||||
select c2, c2 from ft1 where c2 > 6 group by 1, 2 order by sum(c1);
|
||||
c2 | c2
|
||||
@ -2764,16 +2750,13 @@ select c2, c2 from ft1 where c2 > 6 group by 1, 2 order by sum(c1);
|
||||
-- Testing HAVING clause shippability
|
||||
explain (verbose, costs off)
|
||||
select c2, sum(c1) from ft2 group by c2 having avg(c1) < 500 and sum(c1) < 49800 order by c2;
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------------------------------------------------------------------------
|
||||
Sort
|
||||
QUERY PLAN
|
||||
------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Foreign Scan
|
||||
Output: c2, (sum(c1))
|
||||
Sort Key: ft2.c2
|
||||
-> Foreign Scan
|
||||
Output: c2, (sum(c1))
|
||||
Relations: Aggregate on (public.ft2)
|
||||
Remote SQL: SELECT c2, sum("C 1") FROM "S 1"."T 1" GROUP BY 1 HAVING ((avg("C 1") < 500::numeric)) AND ((sum("C 1") < 49800))
|
||||
(7 rows)
|
||||
Relations: Aggregate on (public.ft2)
|
||||
Remote SQL: SELECT c2, sum("C 1") FROM "S 1"."T 1" GROUP BY 1 HAVING ((avg("C 1") < 500::numeric)) AND ((sum("C 1") < 49800)) ORDER BY c2 ASC NULLS LAST
|
||||
(4 rows)
|
||||
|
||||
select c2, sum(c1) from ft2 group by c2 having avg(c1) < 500 and sum(c1) < 49800 order by c2;
|
||||
c2 | sum
|
||||
@ -2823,16 +2806,13 @@ select sum(c1) from ft1 group by c2 having avg(c1 * (random() <= 1)::int) > 100
|
||||
-- ORDER BY within aggregate, same column used to order
|
||||
explain (verbose, costs off)
|
||||
select array_agg(c1 order by c1) from ft1 where c1 < 100 group by c2 order by 1;
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------------------------------------------------------------------
|
||||
Sort
|
||||
QUERY PLAN
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Foreign Scan
|
||||
Output: (array_agg(c1 ORDER BY c1)), c2
|
||||
Sort Key: (array_agg(ft1.c1 ORDER BY ft1.c1))
|
||||
-> Foreign Scan
|
||||
Output: (array_agg(c1 ORDER BY c1)), c2
|
||||
Relations: Aggregate on (public.ft1)
|
||||
Remote SQL: SELECT array_agg("C 1" ORDER BY "C 1" ASC NULLS LAST), c2 FROM "S 1"."T 1" WHERE (("C 1" < 100)) GROUP BY 2
|
||||
(7 rows)
|
||||
Relations: Aggregate on (public.ft1)
|
||||
Remote SQL: SELECT array_agg("C 1" ORDER BY "C 1" ASC NULLS LAST), c2 FROM "S 1"."T 1" WHERE (("C 1" < 100)) GROUP BY 2 ORDER BY array_agg("C 1" ORDER BY "C 1" ASC NULLS LAST) ASC NULLS LAST
|
||||
(4 rows)
|
||||
|
||||
select array_agg(c1 order by c1) from ft1 where c1 < 100 group by c2 order by 1;
|
||||
array_agg
|
||||
@ -2869,16 +2849,13 @@ select array_agg(c5 order by c1 desc) from ft2 where c2 = 6 and c1 < 50;
|
||||
-- DISTINCT within aggregate
|
||||
explain (verbose, costs off)
|
||||
select array_agg(distinct (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1;
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Sort
|
||||
QUERY PLAN
|
||||
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Foreign Scan
|
||||
Output: (array_agg(DISTINCT (t1.c1 % 5))), ((t2.c1 % 3))
|
||||
Sort Key: (array_agg(DISTINCT (t1.c1 % 5)))
|
||||
-> Foreign Scan
|
||||
Output: (array_agg(DISTINCT (t1.c1 % 5))), ((t2.c1 % 3))
|
||||
Relations: Aggregate on ((public.ft4 t1) FULL JOIN (public.ft5 t2))
|
||||
Remote SQL: SELECT array_agg(DISTINCT (r1.c1 % 5)), (r2.c1 % 3) FROM ("S 1"."T 3" r1 FULL JOIN "S 1"."T 4" r2 ON (((r1.c1 = r2.c1)))) WHERE (((r1.c1 < 20) OR ((r1.c1 IS NULL) AND (r2.c1 < 5)))) GROUP BY 2
|
||||
(7 rows)
|
||||
Relations: Aggregate on ((public.ft4 t1) FULL JOIN (public.ft5 t2))
|
||||
Remote SQL: SELECT array_agg(DISTINCT (r1.c1 % 5)), (r2.c1 % 3) FROM ("S 1"."T 3" r1 FULL JOIN "S 1"."T 4" r2 ON (((r1.c1 = r2.c1)))) WHERE (((r1.c1 < 20) OR ((r1.c1 IS NULL) AND (r2.c1 < 5)))) GROUP BY 2 ORDER BY array_agg(DISTINCT (r1.c1 % 5)) ASC NULLS LAST
|
||||
(4 rows)
|
||||
|
||||
select array_agg(distinct (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1;
|
||||
array_agg
|
||||
@ -2890,16 +2867,13 @@ select array_agg(distinct (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2
|
||||
-- DISTINCT combined with ORDER BY within aggregate
|
||||
explain (verbose, costs off)
|
||||
select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1;
|
||||
QUERY PLAN
|
||||
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Sort
|
||||
QUERY PLAN
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Foreign Scan
|
||||
Output: (array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5))), ((t2.c1 % 3))
|
||||
Sort Key: (array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5)))
|
||||
-> Foreign Scan
|
||||
Output: (array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5))), ((t2.c1 % 3))
|
||||
Relations: Aggregate on ((public.ft4 t1) FULL JOIN (public.ft5 t2))
|
||||
Remote SQL: SELECT array_agg(DISTINCT (r1.c1 % 5) ORDER BY ((r1.c1 % 5)) ASC NULLS LAST), (r2.c1 % 3) FROM ("S 1"."T 3" r1 FULL JOIN "S 1"."T 4" r2 ON (((r1.c1 = r2.c1)))) WHERE (((r1.c1 < 20) OR ((r1.c1 IS NULL) AND (r2.c1 < 5)))) GROUP BY 2
|
||||
(7 rows)
|
||||
Relations: Aggregate on ((public.ft4 t1) FULL JOIN (public.ft5 t2))
|
||||
Remote SQL: SELECT array_agg(DISTINCT (r1.c1 % 5) ORDER BY ((r1.c1 % 5)) ASC NULLS LAST), (r2.c1 % 3) FROM ("S 1"."T 3" r1 FULL JOIN "S 1"."T 4" r2 ON (((r1.c1 = r2.c1)))) WHERE (((r1.c1 < 20) OR ((r1.c1 IS NULL) AND (r2.c1 < 5)))) GROUP BY 2 ORDER BY array_agg(DISTINCT (r1.c1 % 5) ORDER BY ((r1.c1 % 5)) ASC NULLS LAST) ASC NULLS LAST
|
||||
(4 rows)
|
||||
|
||||
select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1;
|
||||
array_agg
|
||||
@ -2910,16 +2884,13 @@ select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5) from ft4 t1 full join ft
|
||||
|
||||
explain (verbose, costs off)
|
||||
select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5 desc nulls last) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1;
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Sort
|
||||
QUERY PLAN
|
||||
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Foreign Scan
|
||||
Output: (array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5) DESC NULLS LAST)), ((t2.c1 % 3))
|
||||
Sort Key: (array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5) DESC NULLS LAST))
|
||||
-> Foreign Scan
|
||||
Output: (array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5) DESC NULLS LAST)), ((t2.c1 % 3))
|
||||
Relations: Aggregate on ((public.ft4 t1) FULL JOIN (public.ft5 t2))
|
||||
Remote SQL: SELECT array_agg(DISTINCT (r1.c1 % 5) ORDER BY ((r1.c1 % 5)) DESC NULLS LAST), (r2.c1 % 3) FROM ("S 1"."T 3" r1 FULL JOIN "S 1"."T 4" r2 ON (((r1.c1 = r2.c1)))) WHERE (((r1.c1 < 20) OR ((r1.c1 IS NULL) AND (r2.c1 < 5)))) GROUP BY 2
|
||||
(7 rows)
|
||||
Relations: Aggregate on ((public.ft4 t1) FULL JOIN (public.ft5 t2))
|
||||
Remote SQL: SELECT array_agg(DISTINCT (r1.c1 % 5) ORDER BY ((r1.c1 % 5)) DESC NULLS LAST), (r2.c1 % 3) FROM ("S 1"."T 3" r1 FULL JOIN "S 1"."T 4" r2 ON (((r1.c1 = r2.c1)))) WHERE (((r1.c1 < 20) OR ((r1.c1 IS NULL) AND (r2.c1 < 5)))) GROUP BY 2 ORDER BY array_agg(DISTINCT (r1.c1 % 5) ORDER BY ((r1.c1 % 5)) DESC NULLS LAST) ASC NULLS LAST
|
||||
(4 rows)
|
||||
|
||||
select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5 desc nulls last) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1;
|
||||
array_agg
|
||||
@ -2931,16 +2902,13 @@ select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5 desc nulls last) from ft4
|
||||
-- FILTER within aggregate
|
||||
explain (verbose, costs off)
|
||||
select sum(c1) filter (where c1 < 100 and c2 > 5) from ft1 group by c2 order by 1 nulls last;
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------------------------------------------------------------------
|
||||
Sort
|
||||
QUERY PLAN
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Foreign Scan
|
||||
Output: (sum(c1) FILTER (WHERE ((c1 < 100) AND (c2 > 5)))), c2
|
||||
Sort Key: (sum(ft1.c1) FILTER (WHERE ((ft1.c1 < 100) AND (ft1.c2 > 5))))
|
||||
-> Foreign Scan
|
||||
Output: (sum(c1) FILTER (WHERE ((c1 < 100) AND (c2 > 5)))), c2
|
||||
Relations: Aggregate on (public.ft1)
|
||||
Remote SQL: SELECT sum("C 1") FILTER (WHERE (("C 1" < 100) AND (c2 > 5))), c2 FROM "S 1"."T 1" GROUP BY 2
|
||||
(7 rows)
|
||||
Relations: Aggregate on (public.ft1)
|
||||
Remote SQL: SELECT sum("C 1") FILTER (WHERE (("C 1" < 100) AND (c2 > 5))), c2 FROM "S 1"."T 1" GROUP BY 2 ORDER BY sum("C 1") FILTER (WHERE (("C 1" < 100) AND (c2 > 5))) ASC NULLS LAST
|
||||
(4 rows)
|
||||
|
||||
select sum(c1) filter (where c1 < 100 and c2 > 5) from ft1 group by c2 order by 1 nulls last;
|
||||
sum
|
||||
@ -3339,16 +3307,13 @@ select count(*), x.b from ft1, (select c2 a, sum(c1) b from ft1 group by c2) x w
|
||||
-- FULL join with IS NULL check in HAVING
|
||||
explain (verbose, costs off)
|
||||
select avg(t1.c1), sum(t2.c1) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) group by t2.c1 having (avg(t1.c1) is null and sum(t2.c1) < 10) or sum(t2.c1) is null order by 1 nulls last, 2;
|
||||
QUERY PLAN
|
||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Sort
|
||||
QUERY PLAN
|
||||
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
Foreign Scan
|
||||
Output: (avg(t1.c1)), (sum(t2.c1)), t2.c1
|
||||
Sort Key: (avg(t1.c1)), (sum(t2.c1))
|
||||
-> Foreign Scan
|
||||
Output: (avg(t1.c1)), (sum(t2.c1)), t2.c1
|
||||
Relations: Aggregate on ((public.ft4 t1) FULL JOIN (public.ft5 t2))
|
||||
Remote SQL: SELECT avg(r1.c1), sum(r2.c1), r2.c1 FROM ("S 1"."T 3" r1 FULL JOIN "S 1"."T 4" r2 ON (((r1.c1 = r2.c1)))) GROUP BY 3 HAVING ((((avg(r1.c1) IS NULL) AND (sum(r2.c1) < 10)) OR (sum(r2.c1) IS NULL)))
|
||||
(7 rows)
|
||||
Relations: Aggregate on ((public.ft4 t1) FULL JOIN (public.ft5 t2))
|
||||
Remote SQL: SELECT avg(r1.c1), sum(r2.c1), r2.c1 FROM ("S 1"."T 3" r1 FULL JOIN "S 1"."T 4" r2 ON (((r1.c1 = r2.c1)))) GROUP BY 3 HAVING ((((avg(r1.c1) IS NULL) AND (sum(r2.c1) < 10)) OR (sum(r2.c1) IS NULL))) ORDER BY avg(r1.c1) ASC NULLS LAST, sum(r2.c1) ASC NULLS LAST
|
||||
(4 rows)
|
||||
|
||||
select avg(t1.c1), sum(t2.c1) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) group by t2.c1 having (avg(t1.c1) is null and sum(t2.c1) < 10) or sum(t2.c1) is null order by 1 nulls last, 2;
|
||||
avg | sum
|
||||
|
Reference in New Issue
Block a user