RedShift: Unnest subquery's result on leader is not supported - amazon-redshift

I try to parse JSON in RedShift.
My string in column "inputs" is:
[{"desc": "How many people does the video contain?", "name": "Number of People", "type": "dropdown", "values": ["", "Only 1", "2-3", "3+"]}, {"desc": "What is the camera position?", "name": "Movement", "type": "dropdown", "values": ["", "Fixed position", "Moving"]}, {"desc": "From which angle did you shoot the video?", "name": "Shoot Angle", "type": "dropdown", "values": ["", "Frontal recording", "Tight angle: 10-40 degree", "Wide angle: 40-70 degree"]}, {"desc": "From which distance did you shoot the video?", "name": "Distance", "type": "dropdown", "values": ["", "Near/Selfie", "Mid (3-6 ft)", "Far (>6 ft)"]}, {"desc": "What is the video lighting direction?", "name": "Lighting Direction", "type": "dropdown", "values": ["", "Front lit", "Side lit", "Back lit"]}, {"desc": "What is the video background?", "name": "Background", "type": "dropdown", "values": ["", "Outdoors", "In office", "At home", "Plain background"]}, {"desc": "What is the topic in your speech?", "name": "Topic", "type": "dropdown", "values": ["", "Arts and Media", "Business", "Education", "Entertainment", "Food/Eating", "Nutrition", "Healthcare ", "High School Life", "Mental Health", "News", "Technology", "Morals and Ethics", "Phones and Apps", "Sports", "Science"]}]
My task is: "Each value, name, desc from JSON need to be stored as one row in the table".
Example:
id: 1, desc: "How many people does the video contain?"
id: 2, desc: "What is the camera position?"
etc.
I use query:
SELECT c.*, d.desc, d.name, d.values FROM source.table AS c, c.inputs AS d;
And got an ERROR: navigation on column "inputs" is not allowed as it is not SUPER type
And query:
SELECT c.*, d.desc, d.name, d.values FROM source.table AS c, JSON_PARSE(c.inputs) AS d;
gives me another error: "function expression in FROM may not refer to other relations of same query level"
But when I have created test JSON as:
CREATE TABLE test_parse_json_super
(
id smallint,
details super
);
INSERT INTO test_parse_json_super VALUES(1, JSON_PARSE('[{"desc": "How many people does the video contain?", "name": "Number of People", "type": "dropdown", "values": ["", "Only 1", "2-3", "3+"]}, {"desc": "What is the camera position?", "name": "Movement", "type": "dropdown", "values": ["", "Fixed position", "Moving"]}, {"desc": "From which angle did you shoot the video?", "name": "Shoot Angle", "type": "dropdown", "values": ["", "Frontal recording", "Tight angle: 10-40 degree", "Wide angle: 40-70 degree"]}, {"desc": "From which distance did you shoot the video?", "name": "Distance", "type": "dropdown", "values": ["", "Near/Selfie", "Mid (3-6 ft)", "Far (>6 ft)"]}, {"desc": "What is the video lighting direction?", "name": "Lighting Direction", "type": "dropdown", "values": ["", "Front lit", "Side lit", "Back lit"]}, {"desc": "What is the video background?", "name": "Background", "type": "dropdown", "values": ["", "Outdoors", "In office", "At home", "Plain background"]}, {"desc": "What is the topic in your speech?", "name": "Topic", "type": "dropdown", "values": ["", "Arts and Media", "Business", "Education", "Entertainment", "Food/Eating", "Nutrition", "Healthcare ", "High School Life", "Mental Health", "News", "Technology", "Morals and Ethics", "Phones and Apps", "Sports", "Science"]}]'));
and use query "SELECT c.*, d.desc, d.name, d.values FROM test_parse_json_super AS c, c.details AS d;" from official RedShift docs - it's work fine and all data from JSON is parsing to each rows and JSON is correct.
How I can fix query for work with my real data?
Thnx.

It looks like you are confusing the concepts of SUPER data type for sub-select. You cannot cast a string to super (using JSON_PARSE) and then use it as the source of the FROM clause at the same level of the query. I don't have a complete understanding of your situation but I think something like this should get you closer:
SELECT c.*, d.desc, d.name, d.values
FROM (
SELECT *, JSON_PARSE(inputs) AS inputs_super
FROM source.table
) AS c,
JSON_PARSE(c.inputs_super) AS d
;
(This is an off the cuff response to show structure so please forgive any syntax issues)

It will be more correct:
SELECT c.*, d.desc, d.name, d.values
FROM (
SELECT id, created, JSON_PARSE(inputs) AS inputs_super
FROM source.table
WHERE prompttype = 'input'
) AS c,
c.inputs_super AS d
;

I ran into a similar issue. The json has to be parsed in a created table before use, and cannot be referenced via a CTE or subquery and then used. Therefore I believe the answer is:
CREATE TABLE my_table_with_super
AS
(
SELECT c.*,
JSON_PARSE(c.inputs) AS inputs_json_super
FROM source.table c
);
SELECT c.*,
json_row.desc,
json_row.name,
json_row.values
FROM my_table_with_super as c,
c.inputs_json_super as json_row;

Related

Coalesce value bound to object's key into parent's value

I have a PostgreSQL 12.x database. There is a column data in a table typename that contains JSON. The actual JSON data is not fixed to a particular structure; these are some examples:
{"emt": {"key": " ", "source": "INPUT"}, "id": 1, "fields": {}}
{"emt": {"key": "Stack Overflow", "source": "INPUT"}, "id": 2, "fields": {}}
{"emt": {"key": "https://www.domain.tld/index.html", "source": "INPUT"}, "description": {"key": "JSONB datatype", "source": "INPUT"}, "overlay": {"id": 5, "source": "bOv"}, "fields": {"id": 1, "description": "Themed", "recs ": "1"}}
Basically, what I'm trying to come up with is a (database migration) script that will find any object with the keys key and source, take the actual value of key and assign it to the corresponding key/value pair where the object was originally bound to. For instance:
{"emt": " ", "id": 1, "fields": {}}
{"emt": "Stack Overflow", "id": 2, "fields": {}}
{"emt": "https://www.domain.tld/index.html", "description": "JSONB datatype", "overlay": {"id": 5, "source": "bOv"}, "fields": {"id": 1, "description": "Themed", "recs ": "1"}}
I started finding the rows that contained "source": "INPUT" by using:
select * from typename
where jsonb_path_exists(data, '$.** ? (#.type() == "string" && # like_regex "INPUT")');
...but then I'm not sure how to update the returned subset or to loop through it :/
It took me a while but here is the update statement:
update typename
set data = jsonb_set(data, '{emt}', jsonb_extract_path(data, 'emt', 'key')::jsonb, false)
where jsonb_typeof(data -> 'emt') = 'object'
and jsonb_path_exists(data, '$.emt.key ? (#.type() == "string")')
and jsonb_path_exists(data, '$.emt.source ? (#.type() == "string" && # like_regex "INPUT")');
There are probably better ways to implement that where clause, but that one works ;)
One downside is that I had to figure it out how many keys are involved in the update and align it with the number of update statements; e.g.: in the original example there were two keys: emt and description — so it should have been two update statements.

Redshift: can't parse multiple items from list in JSON to each row

I have a JSON in the RedShift.
"value" is stored in the inputs column as JSON text. Create a unique record for each "value". Look at the example below this table:
{"inputs": [{"name": "ambient", "desc": "Select from below the ambient setting that best decribe your environment right now", "values": ["Indoor - Loud", "Indoor - Normal", "Indoor - Whisper", "Outdoor - Loud", "Outdoor - Normal", "Outdoor - Whisper", "Semi-Outdoor - Loud", "Semi-Outdoor - Normal", "Semi-Outdoor - Whisper"]}
As a result it must be like this:
ProjectId : 10. Input value = Indoor – Loud
ProjectId : 10. Input value = Indoor – Normal
ProjectId : 10. Input value Indoor – Whisper
Each value need to be stored as one row in the dim_collect_user_inp_configs table. Example, Indoor-Loud as one row and it will have it’s own unique identifier as prompt_input_value_id, Indoor-Normal as one row and it will have it’s own unique identifier as prompt_input_value_id till the Semi-Outdoor-Whisper.
There could be multiple input “name” in one inputs column. Each name and its value need to be stored separately. Example :
[{"desc": "How many people does the video contain?", "name": "Number of People", "type": "dropdown", "values": ["", "Only 1", "2-3", "3+"]}, {"desc": "What is the camera position?", "name": "Movement", "type": "dropdown", "values": ["", "Fixed position", "Moving"]}, {"desc": "From which angle did you shoot the video?", "name": "Shoot Angle", "type": "dropdown", "values": ["", "Frontal recording", "Tight angle: 10-40 degree", "Wide angle: 40-70 degree"]}, {"desc": "From which distance did you shoot the video?", "name": "Distance", "type": "dropdown", "values": ["", "Near/Selfie", "Mid (3-6 ft)", "Far (>6 ft)"]}, {"desc": "What is the video lighting direction?", "name": "Lighting Direction", "type": "dropdown", "values": ["", "Front lit", "Side lit", "Back lit"]}, {"desc": "What is the video background?", "name": "Background", "type": "dropdown", "values": ["", "Outdoors", "In office", "At home", "Plain background"]}, {"desc": "What is the topic in your speech?", "name": "Topic", "type": "dropdown", "values": ["", "Arts and Media", "Business", "Education", "Entertainment", "Food/Eating", "Nutrition", "Healthcare ", "High School Life", "Mental Health", "News", "Technology", "Morals and Ethics", "Phones and Apps", "Sports", "Science"]}]
I try to do it with this query:
WITH all_values AS (
SELECT projectid AS projectid,
prompttype AS prompttype,
json_extract_path_text(json_extract_array_element_text(inputs, 0, True), 'name') AS name,
json_extract_path_text(json_extract_array_element_text(inputs, 0, True), 'desc') AS description,
json_extract_path_text(json_extract_array_element_text(inputs, 0, True), 'values') AS value,
scriptid AS scriptid,
corpuscode AS corpuscode
FROM source.table
WHERE
prompttype = 'input'
GROUP BY projectid, prompttype, name, description, scriptid, corpuscode, value
LIMIT 10
)
SELECT * FROM all_values;
But now I haven't each row for "value" as I need. :(
Can you help me?
Thnx.

Fusion Chart Hide Number Prefix for One Bar

I need to remove the dollar ($) sign from the top of the first bar which is showing the values $410K,only we need 410K.
enter link description here
"chart": {
"caption": "Daily Revenue by Order",
"subcaption": "Last 2 weeks",
"xaxisname": "Date",
"yaxisname": "Revenue (In USD)",
"numberprefix": "$",
"showvalues": "1",
"theme": "fusion"
},
"data": [{
"label": "Total Order",
"value": "410000"
},
Yes, you need to remove numberPrefix attribute. Using this attribute, you could add the prefix to all the numbers visible on the graph.
Hence the modified code will be following.
"chart": {
"caption": "Daily Revenue by Order",
"subcaption": "Last 2 weeks",
"xaxisname": "Date",
"yaxisname": "Revenue (In USD)",
"showvalues": "1",
"theme": "fusion"
},
"data": [{
"label": "Total Order",
"value": "410000"
},

Mongodb multilingual query

Material collection represents user submissions.
Default language is defined by the user. Other users can extend first submission with some other languages.
When I request a material, maybe I need more than one language, so I think it fits ok with just one collection where I should support multilanguage.
My current desing is like this (document for testing):
{
"activities": [ "Ficha de actividades", "Juego Colectivo" ],
"files": [ "Asociacion_Profesiones.zip"],
"areas": ["Literatura", "Ciencias Naturales", "Ciencias Sociales" ],
"authors": [
{ "author": "César", "email": "xxx#gmail.com"},
{ "author": "José", "email": "xxxx#gmail.com"}
],
"desc": "La leche, el agua, el vino y la bebida",
"state": 1,
"date": ISODate("2017-01-10 19:40:39"),
"updated": null,
"id": 1,
"language": "spanish",
"images": [],
"license": "Creative Commons BY-NC-SA",
"downloads": 0,
"popular": false,
"title": "La bebida",
"file": "1.zip",
"translations": [
{"language": "english", "title": "Beverages", "desc": "Milk, water, wine and all related with drinking", "authors": [], "files": [], "file": "1.zip", "images": [], "downloads": 0, "state": 1, "created": null, "updated": null},
{"language": "french", "title": "le boisson", "desc": "du lait, de l'eau, du vin, boire", "authors": [], "files": [], "file": "1.zip", "images": [], "downloads": 0, "state": 1, "created": null, "updated": null}
]
}
I create a text index focused on title and descripcion (desc) fields.
db.materials.createIndex({ "title": "text", "desc": "text", "translations.title": "text", "translations.desc": "text"})
I know the user default language, but I don't know how he should make the search.
Imagine an spanish user want to search for drinks:
db.materials.find( { $text: { $search: "drink", $language: "es"} } ).explain(true)
It returns our document. It searches drink, and as "Milk, water, wine and all related with drinking" has drink as stemming for drinking it works ok.
However... if I look for water:
db.materials.find( { $text: { $search: "water", $language: "es"} } ).explain(true)
It returns nothing. water gets converted to wat (as spanish verbs end with er suffix) and "wat" is not found.
Any improvement to my searches?
The only workaround I can imagine is to add language dropdown selector to user searches.

Why is image_hash empty for some ad_creatives? Is it because it is expired?

I ran _">https://graph.facebook.com/act_47121778/adcreatives?access_token=_
and got the following results. Why are some creatives returning empty image hash?
{
"view_tag": "",
"alt_view_tags": [
],
"creative_id": "6002716206572",
"type": 1,
"title": "Grow your fans!",
"body": "Fan Page Owners! Grow your fanbase. Create quizzes for your page. Win $100 Weekly. Make money with our revenue share program.",
"image_hash": "6ac30e43f21c8580361de92d3288ed68",
"link_url": "http://www.facebook.com/quizwriter?sk=app_81434956828",
"name": "Grow your fans!",
"run_status": 1,
"preview_url": "http://www.facebook.com/ads/api/creative_preview.php?cid=6002716206572",
"count_current_adgroups": 1,
"id": "6002716206572",
"image_url": "http://creative.ak.fbcdn.net/v41818/flyers/109/44/1296329249810543669_1_31eb15ed.jpg"
},
{
"view_tag": "",
"alt_view_tags": [
],
"creative_id": "6002444043572",
"type": 1,
"title": "Tennis Champs Social Game",
"body": "Tennis Champ! Start with 5,000 dollars , beat out other players with your mad tennis skills and become the tennis champ! Socialize!",
"image_hash": "",
"link_url": "334886511760",
"name": "Tennis Champs Social Game",
"run_status": 1,
"preview_url": "http://www.facebook.com/ads/api/creative_preview.php?cid=6002444043572",
"count_current_adgroups": 2,
"id": "6002444043572"
},