Correlated ARRAY sub-query?
> On Feb 12, 2022, at 10:40 AM, Gavin Ray <[email protected]> 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 <[email protected]> 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 <[email protected]>
>> 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 <[email protected]>
>> 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 <[email protected]>
>>>> 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 <[email protected]>
>>>>> 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 <[email protected]>
>>>>>> 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 <[email protected]>
>>>>>> 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
>>>>>>>>
>>>>>>
>>>>>>
>>
>>