Alasql: Nested Arrays

Created on 15 Feb 2017  路  14Comments  路  Source: agershun/alasql

Hi,

I'm trying tu use the AlaSQL Array agregator inside an array, it appears to be not supported :(

Trying to acomplish this JSon output (or like this):

[
    {
        "keyword":"project 1",
        "projects": [
            {
                "year":2014,
                "description":"this is a project description",
                "budget": 5600,
                "status": "closed",
                "metadata": [
                    {
                        "key":"provider",
                        "value":"just me"
                    },
                    {
                        "key":"client",
                        "value":"someone"
                    },
                    {
                        "key":"any thing",
                        "value":"any data..."
                    }
                ]
            }
        ]
    }
]

My Database Structure

people e
| name      | type    |
|-----------|---------|
| name      | varchar |
| lastname  | varchar |
| person_id | varchar |
| cel       | int     |

projects p
| name        | type    |
|-------------|---------|
| keyword     | varchar |
| year        | int     |
| description | text    |
| budget      | int     |

PeopleProjects x
| name        | type    |
|-------------|---------|
| e_person_id | varchar |
| p_keyword   | varchar |
| p_year      | int     |
| status      | varchar |

metadata m
| name        | type    |
|-------------|---------|
| e_person_id | varchar |
| p_keyword   | varchar |
| p_year      | int     |
| key         | varchar |
| value       | varchar |

My query

alasql("SELECT p.keyword, \
ARRAY({year:p.year, description:p.description, budget:p.budget, status:x.status, \
    ARRAY({key:m.key, value:m.value}) as metadata \
}) AS projects \
FROM projects p, PeopleProjects x, metadata m \
WHERE \
    p.keyword = x.p_keyword AND x.p_keyword = m.p_keyword AND \
    p.year = x.p_year AND x.p_year = m.p_year \
    x.e_person_id = x.e_person_id AND AND x.e_person_id = 2 \
GROUP BY p.keyword");

At the moment, I divided the query in two and then combine the data to produce the hole thing.

Any ideas?

! Question

All 14 comments

You really should post questions like this on stack overflow.

Please provide your expected result from the SQL given the input that you gave as example

Hi Mathias,

At the time I post this, stackoverflow was having problems with publishing, that's why I did it here. I tried now and succeed.

As I originally say, I'm expecting this output:

[
    {
        "keyword":"project 1",
        "projects": [
            {
                "year":2014,
                "description":"this is a project description",
                "budget": 5600,
                "status": "closed",
                "metadata": [
                    {
                        "key":"provider",
                        "value":"just me"
                    },
                    {
                        "key":"client",
                        "value":"someone"
                    },
                    {
                        "key":"any thing",
                        "value":"any data..."
                    }
                ]
            }
        ]
    }
]

Regards!

Sorry - I was too quick reading this on. You did provide all the data needed in your first post.

I really suggest you do a looped based build of your output. AlaSQL is good to "flatten" results, not to create nested json structures.

Let me know if you need any inptus to this

Anyone?

Also asked this in Stackoverflow, same luck...

(http://stackoverflow.com/questions/42298265/alasql-nested-arrays)

I really suggest you do a loop based formatting of your desired output.

If you want inputs let me know

Thanks! I managed to get the output the best I could, but my solution is far from perfection.

It would be nice to see what you suggest!

I have many things to do. If you found a solution that works, im happy...

As I say in my original post:

At the moment, I divided the query in two and then combine the data to produce the hole thing.

Far for scalable.

Can you leave me a clue?

I have no better way than to combine data from several SQLs

As access is cheap (the data is in memory - and not in the cloud somewhere) we can be more relaxed with how many times we do SQLs

if this is not ment to be running more than 1 time per second and the data is less than a few hundred rows I would not spend much time optimizing but just go along something like:

var sqlGetProject = function(){/*
SELECT year, 
       description, 
       budget, 
       status 
FROM   projects 
       JOIN peopleprojects 
         ON p_keyword = keyword 
            AND p_year = year 
WHERE  keyword = ? 
           */};

var sqlGetMetadata = function(){/*
SELECT `key`, `value`
FROM   projects 
       JOIN metadata 
         ON p_keyword = keyword 
            AND p_year = year 
WHERE  keyword = ? 
               AND 
               year = ?
           */};


var data = [];
alasql('column of select distinct `keyword` from projects').foreach(keyword=>data.push({ keyword:keyword,projects:getProjects(keyword)}))
console.log(data);

function getProjects(keyword){
    let projects = [];
    alasql(sqlGetProject,keyword).foreach(project=>{
                 project.metadata = alasql(sqlGetMetadata,[project.keyword, project.year])
                 projects.push(project);
            })
    return projects
}

AlaSQL does not schedule the query, so we dont gain much from only fetching the results only once (to cut the overhead of involving the database)

Please note that function(){/*select 'MY MULTILINE SQL'*/} will execute the SQL in the comment.

Thanks a lot!

What was your solution? lets see if we had the same ideas

I managed to get the output I want by fetching two times:

First, projects:

var projects = alasql("SELECT p.keyword, ARRAY({status:x.status, year:p.year, description:p.description, budget:p.budget }) AS years \
FROM PeopleProjects x, projects p \
WHERE x.p_keyword = p.keyword AND x.p_year = p.year AND x.e_person_id = "+person_id+" \
GROUP BY p.keyword");

Second, metadata:

var mdata = alasql("SELECT m.e_person_id, m.p_keyword, m.p_year, ARRAY({key:m.key,value:m.value}) as [metadata] \
FROM metadata m, PeopleProjects x \
WHERE x.e_person_id = m.e_person_id AND x.p_keyword = m.p_keyword AND x.p_year = m.p_year AND x.e_person_id = "+person_id+" \
GROUP BY m.e_person_id, m.p_keyword, m.p_year");

Then, loop over projects, searching and storing the metadata:

for(i=0;i<projects.length;i++){
    for(j=0;j<projects[i].years.length;j++){
        current = projects[i].keyword;
        current_year = projects[i].years[0].year;
        search = alasql("SEARCH / * WHERE(year="+current_year+" AND keyword='"+current+"') FROM ?",[mdata]);

        projects[i].years[j]["metadata"] = search[0].metadata;
    }
}

Now projects has all the data.

This is really nice too.

I especially like the ARRAY(...) where you generate the object on the fly

Was this page helpful?
0 / 5 - 0 ratings

Related issues

DickSwart picture DickSwart  路  6Comments

SamanthaAdrichem picture SamanthaAdrichem  路  4Comments

cscan picture cscan  路  4Comments

carloszimm picture carloszimm  路  3Comments

fredt34 picture fredt34  路  5Comments