Okay, I think maybe I have an idea what is going on The parser grammar for "JsonNameAndValue": https://github.com/apache/calcite/blob/82dd78a14f6aef2eeec2f9c94978d04b4acc5359/core/src/main/codegen/templates/Parser.jj#L6267-L6296
Has: e = Expression(ExprContext.ACCEPT_NON_QUERY) This enum value appears to be the one that says it can't contain queries: https://github.com/apache/calcite/blob/82dd78a14f6aef2eeec2f9c94978d04b4acc5359/core/src/main/java/org/apache/calcite/sql/parser/SqlAbstractParserImpl.java#L328-L331 /** * Accept only non-query expressions in this context. */ ACCEPT_NON_QUERY, So it's not a bug, but Calcite's parser just doesn't take query expressions for JSON values. I guess that changing this might break a bunch of stuff, and probably is very difficult? On Wed, Feb 23, 2022 at 6:10 PM Gavin Ray <ray.gavi...@gmail.com> wrote: > Sorry, I realized this might be a time investment to try to debug/reproduce > So I found a website that let me create the schema, rows, and query on > various DB's > > Here is an example on Oracle and MySQL that you can view/modify in your > browser: > > ORACLE: > https://dbfiddle.uk/?rdbms=oracle_21&fiddle=2eed69c44fa63adf9830213163ba73d0 > MYSQL: > https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=f94c7957eae4f5ebe4c879c17fbe64ea > > On Wed, Feb 23, 2022 at 2:59 PM Gavin Ray <ray.gavi...@gmail.com> wrote: > >> I think this actually is a bug in Calcite's parser or it's interpretation >> I tested on H2, Oracle, and MySQL, the below is valid on those DB's but >> fails on Calcite's parser: >> >> ================= >> H2/Oracle >> ================= >> SELECT >> "houses"."id" AS "id", >> "houses"."address" AS "address", >> ( >> SELECT >> JSON_ARRAYAGG(JSON_OBJECT( >> KEY 'id' VALUE "users"."id", >> KEY 'name' VALUE "users"."name", >> KEY 'todos' VALUE ( >> SELECT >> JSON_ARRAYAGG(JSON_OBJECT( >> KEY 'id' VALUE "todos"."id", >> KEY 'description' VALUE "todos"."description" >> )) >> FROM >> "todos" >> WHERE >> "todos"."user_id" = "users"."id" >> ) >> )) >> FROM >> "users" >> WHERE >> "users"."house_id" = "houses"."id" >> ) "users" >> FROM >> "houses" >> GROUP BY >> "houses"."id", >> "houses"."address" >> >> ================= >> MySQL >> ================= >> SELECT >> `houses`.`id` AS `id`, >> `houses`.`address` AS `address`, >> ( >> SELECT >> JSON_ARRAYAGG(JSON_OBJECT( >> 'id', `users`.`id`, >> 'name', `users`.`name`, >> 'todos', ( >> SELECT >> JSON_ARRAYAGG(JSON_OBJECT( >> 'id', `todos`.`id`, >> 'description', `todos`.`description` >> )) >> FROM >> `todos` >> WHERE >> `todos`.`user_id` = `users`.`id` >> ) >> )) >> FROM >> `users` >> WHERE >> `users`.`house_id` = `houses`.`id` >> ) `users` >> FROM >> `houses` >> GROUP BY >> `houses`.`id`, >> `houses`.`address` >> >> On Wed, Feb 23, 2022 at 12:52 PM Gavin Ray <ray.gavi...@gmail.com> wrote: >> >>> That's a valid point, let me see check what some common dialects will >>> accept for this sort of thing >>> >>> On Wed, Feb 23, 2022 at 12:36 PM Julian Hyde <jhyde.apa...@gmail.com> >>> wrote: >>> >>>> It’s a parser error. That usually means that the user has made a >>>> mistake. >>>> >>>> Try your SQL on another DB with JSON support before you declare this a >>>> Calcite bug. >>>> >>>> Julian >>>> >>>> > On Feb 23, 2022, at 09:22, Gavin Ray <ray.gavi...@gmail.com> wrote: >>>> > >>>> > No dice still unfortunately =/ >>>> > >>>> > If it's any easier, I put a self-contained single class reproduction >>>> on >>>> > Github: >>>> > >>>> https://github.com/GavinRay97/calcite-nested-json-subquery-bug/blob/main/src/test/java/com/example/AppTest.java >>>> > >>>> > Is it worth filing a JIRA ticket over you think? >>>> > >>>> > >>>> >> On Wed, Feb 23, 2022 at 3:45 AM Julian Hyde <jhyde.apa...@gmail.com> >>>> wrote: >>>> >> >>>> >> Try ‘value ((‘ in place of ‘value (‘. >>>> >> >>>> >> Julian >>>> >> >>>> >>>> On Feb 21, 2022, at 9:33 AM, Gavin Ray <ray.gavi...@gmail.com> >>>> wrote: >>>> >>> >>>> >>> I hadn't thought about the fact that ORM's probably have to solve >>>> this >>>> >>> problem as well >>>> >>> That is a great suggestion, I will try to investigate some of the >>>> popular >>>> >>> ORM codebases and see if there are any tricks they are using. >>>> >>> >>>> >>> I seem to maybe be getting a tiny bit closer by using subqueries >>>> like >>>> >>> Julian suggested instead of operator calls >>>> >>> But if I may ask what is probably a very stupid question: >>>> >>> >>>> >>> What might the error message >>>> >>> "parse failed: Query expression encountered in illegal context >>>> >>> (state=,code=0)" >>>> >>> >>>> >>> Mean in the below query? >>>> >>> >>>> >>> The reason why I am confused is because the query runs if I remove >>>> the >>>> >>> innermost subquery ("todos") >>>> >>> But the innermost subquery is a direct copy-paste of the subquery >>>> above >>>> >> it, >>>> >>> so I know it MUST be valid >>>> >>> >>>> >>> As usual, thank you so much for your help/guidance Stamatis. >>>> >>> >>>> >>> select >>>> >>> "g0"."id" "id", >>>> >>> "g0"."address" "address", >>>> >>> ( >>>> >>> select json_arrayagg(json_object( >>>> >>> key 'id' value "g1"."id", >>>> >>> key 'todos' value ( >>>> >>> select json_arrayagg(json_object( >>>> >>> key 'id' value "g2"."id", >>>> >>> key 'description' value "g2"."description", >>>> >>> )) >>>> >>> from ( >>>> >>> select * from "todos" >>>> >>> where "g1"."id" = "user_id" >>>> >>> order by "id" >>>> >>> ) "g2" >>>> >>> ) >>>> >>> )) >>>> >>> from ( >>>> >>> select * from "users" >>>> >>> where "g0"."id" = "house_id" >>>> >>> order by "id" >>>> >>> ) "g1" >>>> >>> ) "users" >>>> >>> from "houses" "g0" >>>> >>> order by "g0"."id" >>>> >>> >>>> >>>> On Mon, Feb 21, 2022 at 8:07 AM Stamatis Zampetakis < >>>> zabe...@gmail.com> >>>> >>>> wrote: >>>> >>>> >>>> >>>> Hi Gavin, >>>> >>>> >>>> >>>> A few more comments in case they help to get you a bit further on >>>> your >>>> >>>> work. >>>> >>>> >>>> >>>> The need to return the result as a single object is a common >>>> problem in >>>> >>>> object relational mapping (ORM) frameworks/APIS (JPA, Datanucleus, >>>> >>>> Hibernate, etc.). Apart from the suggestions so far maybe you >>>> could look >>>> >>>> into these frameworks as well for more inspiration. >>>> >>>> >>>> >>>> Moreover your approach of decomposing the query into individual >>>> parts is >>>> >>>> commonly known as the N+1 problem [1]. >>>> >>>> >>>> >>>> Lastly, keep in mind that you can introduce custom UDF, UDAF >>>> functions >>>> >> if >>>> >>>> you need more flexibility on reconstructing the final result. >>>> >>>> >>>> >>>> Best, >>>> >>>> Stamatis >>>> >>>> >>>> >>>> [1] >>>> >>>> >>>> >>>> >>>> >> >>>> https://stackoverflow.com/questions/97197/what-is-the-n1-selects-problem-in-orm-object-relational-mapping >>>> >>>> >>>> >>>>> On Sun, Feb 13, 2022 at 3:59 AM Gavin Ray <ray.gavi...@gmail.com> >>>> >> wrote: >>>> >>>>> >>>> >>>>> Ah wait nevermind, got excited and spoke too soon. Looking at it >>>> more >>>> >>>>> closely, that data isn't correct. >>>> >>>>> At least it's in somewhat the right shape, ha! >>>> >>>>> >>>> >>>>>> On Sat, Feb 12, 2022 at 9:57 PM Gavin Ray <ray.gavi...@gmail.com >>>> > >>>> >> wrote: >>>> >>>>> >>>> >>>>>> After ~5 hours, I think I may have made some progress =) >>>> >>>>>> >>>> >>>>>> I have this, which currently works. The problem is that the >>>> nested >>>> >>>>> columns >>>> >>>>>> don't have names on them. >>>> >>>>>> Since I need to return a nested "Map<String, Object>", I have to >>>> >> figure >>>> >>>>>> out how to convert this query into a form that gives column >>>> names. >>>> >>>>>> >>>> >>>>>> But this is still great progress I think! >>>> >>>>>> >>>> >>>>>> SELECT >>>> >>>>>> "todos".*, >>>> >>>>>> ARRAY( >>>> >>>>>> SELECT >>>> >>>>>> "users".*, >>>> >>>>>> ARRAY( >>>> >>>>>> SELECT >>>> >>>>>> "todos".* >>>> >>>>>> FROM >>>> >>>>>> "todos" >>>> >>>>>> ) AS "todos" >>>> >>>>>> FROM >>>> >>>>>> "users" >>>> >>>>>> ) AS "users" >>>> >>>>>> FROM >>>> >>>>>> "todos" >>>> >>>>>> WHERE >>>> >>>>>> "user_id" IN ( >>>> >>>>>> SELECT >>>> >>>>>> "user_id" >>>> >>>>>> FROM >>>> >>>>>> "users" >>>> >>>>>> WHERE >>>> >>>>>> "house_id" IN ( >>>> >>>>>> SELECT >>>> >>>>>> "id" >>>> >>>>>> FROM >>>> >>>>>> "houses" >>>> >>>>>> ) >>>> >>>>>> ); >>>> >>>>>> >>>> >>>>>> >>>> >>>>>> >>>> >>>>>> >>>> >>>>> >>>> >>>> >>>> >> >>>> +----+---------+------------------------+------------------------------------------------------------------------------+ >>>> >>>>>> | id | user_id | description | >>>> >>>>>> | >>>> >>>>>> >>>> >>>>>> >>>> >>>>> >>>> >>>> >>>> >> >>>> +----+---------+------------------------+------------------------------------------------------------------------------+ >>>> >>>>>> | 1 | 1 | Take out the trash | [{1, John, 1, [{1, 1, >>>> Take >>>> >>>> out >>>> >>>>>> the trash}, {2, 1, Watch my favorite show}, { | >>>> >>>>>> | 2 | 1 | Watch my favorite show | [{1, John, 1, [{1, 1, >>>> Take >>>> >>>> out >>>> >>>>>> the trash}, {2, 1, Watch my favorite show}, { | >>>> >>>>>> | 3 | 1 | Charge my phone | [{1, John, 1, [{1, 1, >>>> Take >>>> >>>> out >>>> >>>>>> the trash}, {2, 1, Watch my favorite show}, { | >>>> >>>>>> | 4 | 2 | Cook dinner | [{1, John, 1, [{1, 1, >>>> Take >>>> >>>> out >>>> >>>>>> the trash}, {2, 1, Watch my favorite show}, { | >>>> >>>>>> | 5 | 2 | Read a book | [{1, John, 1, [{1, 1, >>>> Take >>>> >>>> out >>>> >>>>>> the trash}, {2, 1, Watch my favorite show}, { | >>>> >>>>>> | 6 | 2 | Organize office | [{1, John, 1, [{1, 1, >>>> Take >>>> >>>> out >>>> >>>>>> the trash}, {2, 1, Watch my favorite show}, { | >>>> >>>>>> | 7 | 3 | Walk the dog | [{1, John, 1, [{1, 1, >>>> Take >>>> >>>> out >>>> >>>>>> the trash}, {2, 1, Watch my favorite show}, { | >>>> >>>>>> | 8 | 3 | Feed the cat | [{1, John, 1, [{1, 1, >>>> Take >>>> >>>> out >>>> >>>>>> the trash}, {2, 1, Watch my favorite show}, { | >>>> >>>>>> >>>> >>>>>> >>>> >>>>> >>>> >>>> >>>> >> >>>> +----+---------+------------------------+------------------------------------------------------------------------------+ >>>> >>>>>> >>>> >>>>>> On Sat, Feb 12, 2022 at 4:13 PM Gavin Ray <ray.gavi...@gmail.com >>>> > >>>> >>>> wrote: >>>> >>>>>> >>>> >>>>>>> Nevermind, this is a standard term not something >>>> Calcite-specific it >>>> >>>>>>> seems! >>>> >>>>>>> >>>> >>>>>>> https://en.wikipedia.org/wiki/Correlated_subquery >>>> >>>>>>> >>>> >>>>>>> On Sat, Feb 12, 2022 at 3:46 PM Gavin Ray < >>>> ray.gavi...@gmail.com> >>>> >>>>> wrote: >>>> >>>>>>> >>>> >>>>>>>> Forgive my ignorance/lack of experience >>>> >>>>>>>> >>>> >>>>>>>> I am somewhat familiar with the ARRAY() function, but not sure >>>> I >>>> >> know >>>> >>>>>>>> the term "correlated" >>>> >>>>>>>> Searching the Calcite codebase for uses of "correlated" + >>>> "query", I >>>> >>>>>>>> found: >>>> >>>>>>>> >>>> >>>>>>>> >>>> >>>>>>>> >>>> >>>>> >>>> >>>> >>>> >> >>>> https://github.com/apache/calcite/blob/1d4f1b394bfdba03c5538017e12ab2431b137ca9/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java#L1603-L1612 >>>> >>>>>>>> >>>> >>>>>>>> @Test void testCorrelatedSubQueryInJoin() { >>>> >>>>>>>> final String sql = "select *\n" >>>> >>>>>>>> + "from emp as e\n" >>>> >>>>>>>> + "join dept as d using (deptno)\n" >>>> >>>>>>>> + "where d.name = (\n" >>>> >>>>>>>> + " select max(name)\n" >>>> >>>>>>>> + " from dept as d2\n" >>>> >>>>>>>> + " where d2.deptno = d.deptno)"; >>>> >>>>>>>> sql(sql).withExpand(false).ok(); >>>> >>>>>>>> } >>>> >>>>>>>> >>>> >>>>>>>> But I also see this, which says it is "uncorrelated" but seems >>>> very >>>> >>>>>>>> similar? >>>> >>>>>>>> >>>> >>>>>>>> @Test void testInUncorrelatedSubQuery() { >>>> >>>>>>>> final String sql = "select empno from emp where deptno in" >>>> >>>>>>>> + " (select deptno from dept)"; >>>> >>>>>>>> sql(sql).ok(); >>>> >>>>>>>> } >>>> >>>>>>>> >>>> >>>>>>>> I wouldn't blame you for not answering such a basic question >>>> -- but >>>> >>>>> what >>>> >>>>>>>> exactly does "correlation" mean here? >>>> >>>>>>>> >>>> >>>>>>>> Thanks, as usual Julian >>>> >>>>>>>> >>>> >>>>>>>> >>>> >>>>>>>> On Sat, Feb 12, 2022 at 3:08 PM Julian Hyde < >>>> jhyde.apa...@gmail.com >>>> >>> >>>> >>>>>>>> wrote: >>>> >>>>>>>> >>>> >>>>>>>>> Correlated ARRAY sub-query? >>>> >>>>>>>>> >>>> >>>>>>>>>> On Feb 12, 2022, at 10:40 AM, Gavin Ray < >>>> ray.gavi...@gmail.com> >>>> >>>>>>>>> wrote: >>>> >>>>>>>>>> >>>> >>>>>>>>>> Apologies for the delay in replying >>>> >>>>>>>>>> >>>> >>>>>>>>>> This makes things clear and seems obvious now that you point >>>> it >>>> >>>> out. >>>> >>>>>>>>>> Thank you, Justin and Julian =) >>>> >>>>>>>>>> >>>> >>>>>>>>>> Let me ask another question (if I may) that I am struggling >>>> to >>>> >>>>> phrase >>>> >>>>>>>>>> easily. >>>> >>>>>>>>>> >>>> >>>>>>>>>> So with GraphQL, you might have a query like: >>>> >>>>>>>>>> - "Get houses" >>>> >>>>>>>>>> - "For each house get the user that lives in the house >>>> >>>>>>>>>> - "And for each user get their list of todos" >>>> >>>>>>>>>> >>>> >>>>>>>>>> The result has to come back such that it's a single object >>>> for >>>> >>>> each >>>> >>>>>>>>> row >>>> >>>>>>>>>> ============== >>>> >>>>>>>>>> { >>>> >>>>>>>>>> houses: [{ >>>> >>>>>>>>>> address: "123 Main Street", >>>> >>>>>>>>>> users: [{ >>>> >>>>>>>>>> name: "Joe", >>>> >>>>>>>>>> todos: [{ >>>> >>>>>>>>>> description: "Take out trash" >>>> >>>>>>>>>> }] >>>> >>>>>>>>>> }] >>>> >>>>>>>>>> } >>>> >>>>>>>>>> >>>> >>>>>>>>>> From a SQL perspective, the logical equivalent would be >>>> something >>>> >>>>>>>>> like: >>>> >>>>>>>>>> ============== >>>> >>>>>>>>>> SELECT >>>> >>>>>>>>>> house.address, >>>> >>>>>>>>>> (somehow nest users + double-nest todos under user) >>>> >>>>>>>>>> FROM >>>> >>>>>>>>>> house >>>> >>>>>>>>>> JOIN >>>> >>>>>>>>>> user ON user.house_id = house.id >>>> >>>>>>>>>> todos ON todos.user_id = user.id >>>> >>>>>>>>>> WHERE >>>> >>>>>>>>>> house.id = 1 >>>> >>>>>>>>>> >>>> >>>>>>>>>> I'm not familiar enough with SQL to have figured out a way >>>> to make >>>> >>>>>>>>> this >>>> >>>>>>>>>> kind of >>>> >>>>>>>>>> query using operators that are supported across most of the >>>> DB's >>>> >>>>>>>>> Calcite has >>>> >>>>>>>>>> adapters for. >>>> >>>>>>>>>> >>>> >>>>>>>>>> Currently what I have done instead, on a tip from >>>> Gopalakrishna >>>> >>>>> Holla >>>> >>>>>>>>> from >>>> >>>>>>>>>> LinkedIn Coral team who has built GraphQL-on-Calcite, was to >>>> break >>>> >>>>> up >>>> >>>>>>>>> the >>>> >>>>>>>>>> query >>>> >>>>>>>>>> into individual parts and then do the join in-memory: >>>> >>>>>>>>>> >>>> >>>>>>>>>> SELECT ... FROM users; >>>> >>>>>>>>>> SELECT ... FROM todos WHERE todos.user_id IN (ResultSet from >>>> prev >>>> >>>>>>>>> response); >>>> >>>>>>>>>> >>>> >>>>>>>>>> However, the way I am doing this seems like it's probably >>>> very >>>> >>>>>>>>> inefficient. >>>> >>>>>>>>>> Because I do a series of nested loops to add the key to each >>>> >>>> object >>>> >>>>>>>>> in the >>>> >>>>>>>>>> parent ResultSet row: >>>> >>>>>>>>>> >>>> >>>>>>>>>> >>>> >>>>>>>>> >>>> >>>>> >>>> >>>> >>>> >> >>>> https://github.com/GavinRay97/GraphQLCalcite/blob/648e0ac4f6810a3c360d13a03e6597c33406de4b/src/main/kotlin/TableDataFetcher.kt#L135-L153 >>>> >>>>>>>>>> >>>> >>>>>>>>>> Is there some better way of doing this? >>>> >>>>>>>>>> I would be eternally grateful for any advice. >>>> >>>>>>>>>> >>>> >>>>>>>>>> >>>> >>>>>>>>>> On Thu, Feb 10, 2022 at 3:27 PM Julian Hyde < >>>> >>>> jhyde.apa...@gmail.com >>>> >>>>>> >>>> >>>>>>>>> wrote: >>>> >>>>>>>>>> >>>> >>>>>>>>>>> Yes, if you want to do multiple layers of aggregation, use >>>> CTEs >>>> >>>>>>>>> (WITH) or >>>> >>>>>>>>>>> nested sub-queries. For example, the following is I believe >>>> valid >>>> >>>>>>>>> standard >>>> >>>>>>>>>>> SQL, and actually computes something useful: >>>> >>>>>>>>>>> >>>> >>>>>>>>>>> WITH q1 AS >>>> >>>>>>>>>>> (SELECT deptno, job, AVG(sal) AS avg_sal >>>> >>>>>>>>>>> FROM emp >>>> >>>>>>>>>>> GROUP BY deptno, job) >>>> >>>>>>>>>>> WITH q2 AS >>>> >>>>>>>>>>> (SELECT deptno, AVG(avg_sal) AS avg_avg_sal >>>> >>>>>>>>>>> FROM q1 >>>> >>>>>>>>>>> GROUP BY deptno) >>>> >>>>>>>>>>> SELECT AVG(avg_avg_sal) >>>> >>>>>>>>>>> FROM q2 >>>> >>>>>>>>>>> GROUP BY () >>>> >>>>>>>>>>> >>>> >>>>>>>>>>> (You can omit the “GROUP BY ()” line, but I think it makes >>>> things >>>> >>>>>>>>> clearer.) >>>> >>>>>>>>>>> >>>> >>>>>>>>>>> Julian >>>> >>>>>>>>>>> >>>> >>>>>>>>>>> >>>> >>>>>>>>>>> >>>> >>>>>>>>>>>> On Feb 10, 2022, at 12:17 PM, Justin Swanhart < >>>> >>>>> greenl...@gmail.com> >>>> >>>>>>>>>>> wrote: >>>> >>>>>>>>>>>> >>>> >>>>>>>>>>>> I wish you could unsend emails :) Answering my own >>>> question, >>>> >>>> no, >>>> >>>>>>>>> because >>>> >>>>>>>>>>>> that would return three rows with the average :D >>>> >>>>>>>>>>>> >>>> >>>>>>>>>>>> On Thu, Feb 10, 2022 at 3:16 PM Justin Swanhart < >>>> >>>>>>>>> greenl...@gmail.com> >>>> >>>>>>>>>>> wrote: >>>> >>>>>>>>>>>> >>>> >>>>>>>>>>>>> Just out of curiosity, is the second level aggregation >>>> using >>>> >>>> AVG >>>> >>>>>>>>> in a >>>> >>>>>>>>>>>>> window context? It the frame is the whole table and it >>>> >>>>> aggregates >>>> >>>>>>>>> over >>>> >>>>>>>>>>> it? >>>> >>>>>>>>>>>>> >>>> >>>>>>>>>>>>> On Thu, Feb 10, 2022 at 3:12 PM Justin Swanhart < >>>> >>>>>>>>> greenl...@gmail.com> >>>> >>>>>>>>>>>>> wrote: >>>> >>>>>>>>>>>>> >>>> >>>>>>>>>>>>>> That is really neat about Oracle. >>>> >>>>>>>>>>>>>> >>>> >>>>>>>>>>>>>> The alternative in general is to use a subquery: >>>> >>>>>>>>>>>>>> SELECT avg(avg(sal)) FROM emp GROUP BY deptno; >>>> >>>>>>>>>>>>>> becomes >>>> >>>>>>>>>>>>>> select avg(the_avg) >>>> >>>>>>>>>>>>>> from (select avg(sal) from emp group b deptno) an_alias; >>>> >>>>>>>>>>>>>> >>>> >>>>>>>>>>>>>> or >>>> >>>>>>>>>>>>>> >>>> >>>>>>>>>>>>>> with the_cte as (select avg(sal) x from emp group by >>>> deptno) >>>> >>>>>>>>>>>>>> select avg(x) from the_cte; >>>> >>>>>>>>>>>>>> >>>> >>>>>>>>>>>>>> On Thu, Feb 10, 2022 at 3:03 PM Julian Hyde < >>>> >>>>>>>>> jhyde.apa...@gmail.com> >>>> >>>>>>>>>>>>>> wrote: >>>> >>>>>>>>>>>>>> >>>> >>>>>>>>>>>>>>> Some databases, e.g. Oracle, allow TWO levels of >>>> nesting: >>>> >>>>>>>>>>>>>>> >>>> >>>>>>>>>>>>>>> SELECT avg(sal) FROM emp GROUP BY deptno; >>>> >>>>>>>>>>>>>>> >>>> >>>>>>>>>>>>>>> AVG(SAL) >>>> >>>>>>>>>>>>>>> ======== >>>> >>>>>>>>>>>>>>> 1,566.67 >>>> >>>>>>>>>>>>>>> 2,175.00 >>>> >>>>>>>>>>>>>>> 2,916.65 >>>> >>>>>>>>>>>>>>> >>>> >>>>>>>>>>>>>>> SELECT avg(avg(sal)) FROM emp GROUP BY deptno; >>>> >>>>>>>>>>>>>>> >>>> >>>>>>>>>>>>>>> AVG(SUM(SAL)) >>>> >>>>>>>>>>>>>>> ============= >>>> >>>>>>>>>>>>>>> 9,675 >>>> >>>>>>>>>>>>>>> >>>> >>>>>>>>>>>>>>> The first level aggregates by department (returning 3 >>>> >>>> records), >>>> >>>>>>>>> and >>>> >>>>>>>>>>> the >>>> >>>>>>>>>>>>>>> second level computes the grand total (returning 1 >>>> record). >>>> >>>> But >>>> >>>>>>>>> that >>>> >>>>>>>>>>> is an >>>> >>>>>>>>>>>>>>> exceptional case. >>>> >>>>>>>>>>>>>>> >>>> >>>>>>>>>>>>>>> Generally, any expression in the SELECT or HAVING >>>> clause of >>>> >>>> an >>>> >>>>>>>>>>> aggregate >>>> >>>>>>>>>>>>>>> query is either ‘before’ or ‘after’ aggregation. >>>> Consider >>>> >>>>>>>>>>>>>>> >>>> >>>>>>>>>>>>>>> SELECT t.x + 1 AS a, 2 + SUM(t.y + 3) AS b >>>> >>>>>>>>>>>>>>> FROM t >>>> >>>>>>>>>>>>>>> GROUP BY t.x >>>> >>>>>>>>>>>>>>> >>>> >>>>>>>>>>>>>>> The expressions “t.y” and “t.y + 3” occur before >>>> aggregation; >>>> >>>>>>>>> “t.x”, >>>> >>>>>>>>>>>>>>> “t.x + 1”, “SUM(t.y + 3)” and “2 + SUM(t.y + 3)” occur >>>> after >>>> >>>>>>>>>>> aggregation. >>>> >>>>>>>>>>>>>>> SQL semantics rely heavily on this stratification. >>>> Allowing >>>> >>>> an >>>> >>>>>>>>> extra >>>> >>>>>>>>>>> level >>>> >>>>>>>>>>>>>>> of aggregation would mess it all up. >>>> >>>>>>>>>>>>>>> >>>> >>>>>>>>>>>>>>> Julian >>>> >>>>>>>>>>>>>>> >>>> >>>>>>>>>>>>>>> >>>> >>>>>>>>>>>>>>> >>>> >>>>>>>>>>>>>>>> On Feb 10, 2022, at 9:45 AM, Justin Swanhart < >>>> >>>>>>>>> greenl...@gmail.com> >>>> >>>>>>>>>>>>>>> wrote: >>>> >>>>>>>>>>>>>>>> >>>> >>>>>>>>>>>>>>>> This is a SQL limitation. >>>> >>>>>>>>>>>>>>>> >>>> >>>>>>>>>>>>>>>> mysql> select sum(1); >>>> >>>>>>>>>>>>>>>> +--------+ >>>> >>>>>>>>>>>>>>>> | sum(1) | >>>> >>>>>>>>>>>>>>>> +--------+ >>>> >>>>>>>>>>>>>>>> | 1 | >>>> >>>>>>>>>>>>>>>> +--------+ >>>> >>>>>>>>>>>>>>>> 1 row in set (0.00 sec) >>>> >>>>>>>>>>>>>>>> >>>> >>>>>>>>>>>>>>>> mysql> select sum(sum(1)); >>>> >>>>>>>>>>>>>>>> ERROR 1111 (HY000): Invalid use of group function >>>> >>>>>>>>>>>>>>>> >>>> >>>>>>>>>>>>>>>> On Thu, Feb 10, 2022 at 12:39 PM Gavin Ray < >>>> >>>>>>>>> ray.gavi...@gmail.com> >>>> >>>>>>>>>>>>>>> wrote: >>>> >>>>>>>>>>>>>>>> >>>> >>>>>>>>>>>>>>>>> Went to test this query out and found that it can't be >>>> >>>>>>>>> performed: >>>> >>>>>>>>>>>>>>>>> >>>> >>>>>>>>>>>>>>>>> SELECT >>>> >>>>>>>>>>>>>>>>> JSON_OBJECT( >>>> >>>>>>>>>>>>>>>>> KEY 'users' >>>> >>>>>>>>>>>>>>>>> VALUE JSON_ARRAYAGG( >>>> >>>>>>>>>>>>>>>>> JSON_OBJECT( >>>> >>>>>>>>>>>>>>>>> KEY 'name' VALUE "users"."name", >>>> >>>>>>>>>>>>>>>>> KEY 'todos' VALUE JSON_ARRAYAGG( >>>> >>>>>>>>>>>>>>>>> JSON_OBJECT( >>>> >>>>>>>>>>>>>>>>> KEY 'description' VALUE >>>> >>>>>>>>> "todos"."description" >>>> >>>>>>>>>>>>>>>>> ) >>>> >>>>>>>>>>>>>>>>> ) >>>> >>>>>>>>>>>>>>>>> ) >>>> >>>>>>>>>>>>>>>>> ) >>>> >>>>>>>>>>>>>>>>> ) >>>> >>>>>>>>>>>>>>>>> FROM >>>> >>>>>>>>>>>>>>>>> "users" >>>> >>>>>>>>>>>>>>>>> LEFT OUTER JOIN >>>> >>>>>>>>>>>>>>>>> "todos" ON "users"."id" = "todos"."user_id"; >>>> >>>>>>>>>>>>>>>>> >>>> >>>>>>>>>>>>>>>>> Checking the source, seems this is a blanket policy, >>>> not a >>>> >>>>>>>>>>>>>>>>> datasource-specific thing. >>>> >>>>>>>>>>>>>>>>> From a functional perspective, it doesn't feel like >>>> it's >>>> >>>> much >>>> >>>>>>>>>>>>>>> different >>>> >>>>>>>>>>>>>>>>> from JOINs >>>> >>>>>>>>>>>>>>>>> But I don't understand relational theory or DB >>>> >>>> functionality >>>> >>>>>>>>> in the >>>> >>>>>>>>>>>>>>> least, >>>> >>>>>>>>>>>>>>>>> so I'm not fit to judge. >>>> >>>>>>>>>>>>>>>>> >>>> >>>>>>>>>>>>>>>>> Just curious why Calcite doesn't allow this >>>> >>>>>>>>>>>>>>>>> >>>> >>>>>>>>>>>>>>> >>>> >>>>>>>>>>>>>>> >>>> >>>>>>>>>>> >>>> >>>>>>>>>>> >>>> >>>>>>>>> >>>> >>>>>>>>> >>>> >>>>> >>>> >>>> >>>> >> >>>> >>>