We have a series of tables with schema that contains a repeated record, like follows:
[{
name: "field1",
type: "RECORD",
mode: "REPEATED",
fields: [{type: "STRING", name: "subfield1"}, {type: "INTEGER", name: "subfield2"}]
}]
when we create a view that include that repeated record field, we always get error:
Error in query string: Field field1 from table xxxxx is not a leaf field.
I understand that it might be better to use flatten, but all this field contains mostly different filters we want to test on and we have a lot of other non-repeated fields that would be difficult to manage if flattened.
It turned out that the problem is selecting the repeated record field from multiple tables (not in creating view). Is there an easy way to get around that?
Thanks
If you do SELECT field.* from t1, t2 you'll get an error that the * cannot be used to refer fields in a union (as you've noticed above).
You can work around this by wrapping the union in an inner SELECT statement, as in SELECT field.* from (SELECT * from t1, t2).
To give a concrete example, this works:
SELECT payload.pages.*
FROM (
SELECT *
FROM [publicdata:samples.github_nested],
[publicdata:samples.github_nested])
Related
I'm trying to create a table with this below data value:
{"name": "Tommy", "Age": 16, "date":{"string": "2020-10-10"}}
{"name": "Will", "Age": 20, "date":{"string": "2020-10-10"}}
but when I try to access data from a select it comes:
{"string":"2020-10-10"}
and I just need data value
there is any option to solve this on create table step? For exemple, to create a table looking to the date["string"] value.
I know, this is very specific, but if someone knows I'll be very happy! Thks
One common way to solve this kind of situation is to use a view. Assuming you have a table called nested_Data with name, age, and date columns where the date column is defined as struct<string:string>, you can create a view like this:
CREATE VIEW flat_data AS
SELECT name, age, date['string'] AS date
FROM nested_data
when you run a query like SELECT date FROM flat_data you will get only the date value.
Views are often used like this when the raw data needs a bit of pre-processing and you want to avoid having to include all that pre-processing in every query.
I'd like to perform a SELECT only when a condition is satisfied.
So far, the most I've come up with is the following:
SELECT id,
CASE WHEN country = 'Germany'
THEN (SELECT population)
END
FROM table;
However, the query returns an empty column named "case", as shown in the image:
Note that I don't want to make the field false or null, I don't even want this column to appear in the resulting table, as I need to use this same query for different databases. For example, the same query that I will use in the database "Germany", where the column "population" exists, should also be used in the database "Italy", where the column "population" does not even exist.
In other words:
If the country is "Germany", I would like to return "id" and "population".
Else, I would like to return only "id".
Note: It needs to be the same query. There is no possibility for me to make a different query for each country.
I am relatively new to ABAP and so I still need to get used to internal tables and the like,
so currently I am a little bit struggling with how to use SQL in ABAP to fill a nested structure.
For example:
TYPES: BEGIN of <<mystructure>>,
someID type sometype,
relatedItemsInDataModel type table of sometabletype,
END of <<mystructure>>.
DATA wa type <<mystructure>>.
<<SELECT INTO STATEMENT>>
DATA(lv_json) = /ui2/cl_json=>serialize( data = wa compress abap_true ... ).
So basically, I've got a table (A) in the dictionary which has a one-to-many relationship to another table (B) and I want to select all items in A and for every item in A I want to select all related items in B for that record.
The reason I wanna do this is because I later on want to convert that data to JSON looking like:
[
{
"someID": "someValue",
"relatedItemsInDataModel": [{...}, {...}]
},
{
"someID": "someValue2",
"relatedItemsInDataModel": [{...}, {...}, {...}, ...]
},
...
]
So, am I approaching this the right way in the first place and how can I achieve what I just described?
SELECTs only retrieve flat tables. Your therefore need to retrieve nested data in multiple steps and assemble it in the ABAP code.
Your example could look like this:
DATA the_ids_i_want TYPE RANGE OF sometype.
SELECT <field-list>
FROM table_a
INTO TABLE #DATA(selection_a)
WHERE some_id IN #the_ids_i_want.
SELECT <field-list>
FROM table_b
INTO TABLE #DATA(selection_b)
WHERE parent_id IN #the_ids_i_want.
LOOP AT selection_a INTO DATA(row_a).
DATA(result_row) =
VALUE <<mystructure>>(
some_id = row_a-some_id ).
LOOP AT selection_b INTO DATA(row_b)
WHERE parent_id = row_a-some_id.
INSERT VALUE #(
field_a = row_b-field_a
... )
INTO TABLE row_a-relatedItemsInDataModel.
ENDLOOP.
ENDLOOP.
There are a lot of aspects that can be optimized, depending on your data. For example, the WHERE conditions may vary depending on the type of foreign key relations, you may want to consider adding sorted keys to the internal table to speed up the LOOP ... WHERE lookup, there may be shorter variants for the assembly, using FOR instead of LOOP AT, etc. - but basically, this is what you need.
I currently have a table sessions with a column actions(JSONB).
I am able to properly store an array from my frontend to my database using array_to_jsonb(array value).
The structure of my array (array value) looks like this:
var arrayStructure = [
{name: 'email client', check: false},
{name: 'send contract', check: false}
]
Unlike a lot of the questions I've seen on SO about modifying JSONB or accessing certain keys, I am only interested in converting the entire JSONB data back to an array for the frontend.
My temporary fix is to map through the array and use JSON.parse() in Javascript to restructure each object in the array. I cannot use JSON.parse() on the entire array, as it throws an error.
I'm looking for a query to bring back the array format to the JSONB data type stored. I've seen JSONB_SET, LATERAL, AND JSONB_ARRAY_ELEMENTS_TEXT. But not in a way that worked to bring back a proper array.
Starts As: JSONB in actions column in table named sessions
Should Result In: A query that brings back all rows, but with the actions column (JSONB) converted back to an array for the frontend:
select session_id, session_name, someFunction or lateral here(actions) from sessions
Screenshot of Sessions Table
I've tried queries like this:
SELECT
session_id,
actions::jsonb -> 'name' as name
FROM sessions;
And receive back null for name. I've tried ->> to access a deeper level, but that didn't work either.
This is half of the correct query result:
select session_id, jsonb_array_elements_text(actions)
from sessions
group by session_id;
Which results in this (only pay attention to results for session_id of 264):
query result
Now I have objects in their own rows as:
{"name": "some task", "check": "false}
When what I want for the actions column is:
[ {name: "some task", check: false}, {name: "other task", check: true} ]
So I need to further parse the JSON and group by session_id. I'm just struggling to build a sub-query that does that.
Steps to Create Set Up:
create table fakeSessions (
session_id serial primary key,
name varchar(20),
list jsonb
)
insert into fakeSessions(name, list)
VALUES(
'running',
'["{\"name\":\"inquired\",\"check\":false}", "{\"name\":\"sent online guide\",\"check\":false}", "{\"name\":\"booked!\",\"check\":false}"]'
)
insert into fakeSessions(name, list)
VALUES(
'snowboarding',
'["{\"name\":\"rental\",\"check\":false}", "{\"name\":\"booked ski passes\",\"check\":false}", "{\"name\":\"survey\",\"check\":false}"]'
)
The closest query I've created:
with exports as (
select jsonb_array_elements_text(actions)::jsonb as doc from sessions
)
select array_agg(doc) from
exports, sessions
group by session_id;
Get the text values, and then apply an aggregate function to those returned rows. Just can't get the select array_agg(doc) to work as expected. Most likely because I need a different function in that place.
Does this help?
demo:db<>fiddle
SELECT
jsonb_agg(elem)
FROM
sessions, jsonb_array_elements(actions) as elem
jsonb_array_elements() expands the jsonb array into one row each jsonb element
jsonb_agg() aggregates these jsonb elements into one big array.
I was able to reach the answer by building off of your query! Thank you so much. The query that got the expected outcome was this:
with exports as (
select session_id, jsonb_array_elements_text(actions)::jsonb as doc from sessions
)
select session_id, jsonb_agg(doc) from exports
group by session_id;
I wasn't using the jsonb_agg() function once I got the elements. The difference for getting the exact format was just using jsonb_array_elements_text::jsonb
My apologies for wrong terminilogies, I am not actually a programmer, just a Base user confronted with a problem.
I'm having trouble querying a column which is supposed to be a concatenation of two fields of two separate tables. I'm using LibreOffice Base Version 1:3.6.2 and it has the default HSQL engine.
My two tables are as follows:
Table 1 is named "Prefectures" and has the following fields: ID, "Prefecture Name", and "State"
Table 2 is named "Ward" and has the following fields: ID, "Ward Name", and Prefecture ID which is a foreign key referencing table 1.
What I want my query to produce is these two colums: "Ward Name, Prefecture Name" as a concatenation of the Ward.WardName and Prefecture.PrefectureName, and the Ward ID
For example. If I had a prefecture named "Cebu" and a ward named "Lahug" which has a ward ID of 0, I want the query to come up with "Lahug, Cebu" on column 1, and "0" in column 2
The Base tutorial I used seems to have a modified language compared to the actual HSQL language, at least based on my programmer friends reaction. I know that attributes are referred to as Table.Attribute, for example, but in Base, they use "Attribute", or, if I am not mistaken, when one needs to specify the table of origin, "Table"("Attribute"). However, I know that this modified language works because I used it to create the my two tables.
Anyways, hazarding on what I learned from Base the tutorial document, I came up with:
SELECT "Ward Name" || ', ' || "Prefecture Name" AS "Wrd_Pref",
"Ward ID"
FROM "Prefecture" INNER JOIN "Ward" ON "Prefecture" ("Prefecture ID") = "Ward" ("Prefecture ID")
;
And the error message that came up was:
"The data content could not be loaded. Access is denied: PREFECTURE in statement [the whole code above]"
I have a suspicion this is a misread due to wrong syntax on my part. Perhaps my guess on using perentheses in this case is wrong? If so, why is the error message "Access denied"? I checked both the records and the sql codes of the two tables, both were perfectly normal.
EDIT: No, I don't want to just split the two fields. I need them concatenated as I am going to use them as list items in a dropdown list for a form I am making.
The SQL query is this one. You say your tables are called "Prefectures" and "Ward", which are used in the FROM clause.
SELECT "Ward Name" || ', ' || "Prefecture Name" AS "Wrd_Pref", "Ward ID"
FROM "Prefectures" INNER JOIN "Ward" ON "Prefectures"."Prefecture ID" = "Ward"."Prefecture ID";