Snowflake: how to form a string from an ARRAY with OBJECT types inside? - snowflake-cloud-data-platform

I have a column TAGS of type ARRAY in table ITEM that looks like this:
TAGS
[{"Name": 'Alice', "Department": 'Sales', "ID": 123}, {"Name": 'Bob', "Department": 'HR', "ID": 456}]
[{"Name": 'Charles', "Department": 'Director', "ID": 789}]
As you can see, the number of elements inside the ARRAY does not match. What I want is to construct a string for each row, that gets only the Name and ID of all elements, separated by the character ,. This is the desired result:
TAGS
'Alice: 123, Bob: 456'
'Charles: 789'
How can I do that in Snowflake? Ideally, I would like to use it in a SELECT statement.

I am able to figure this out. The trick is to use a combination of LATERAL FLATTEN and LISTAGG. A requirement is the table must have an ID associated with a row (which can be easily generated):
ID
TAGS
1
[{"Name": 'Alice', "Department": 'Sales', "ID": 123}, {"Name": 'Bob', "Department": 'HR', "ID": 456}]
2
[{"Name": 'Charles', "Department": 'Director', "ID": 789}]
Then we can use:
select list_agg(value:"Name"::varchar || ': ' || value:"ID"::varchar, ', ')
from ITEM,
lateral flatten(input => ITEM.TAGS)
group by ID;

Related

snowflake, how to combine all result into json when doing a group by

I have a table with values like this
table-1
id
value-1
value-2
id-1
test
{"id": "value","other": "this"}
id-2
foo-1
{"id": "value","other": "this"}
id-2
foo-2
{"id": "value1","other": "this"}
I want to be able to group by column id and produce results like
id
json_value
id-1
[{"value-1": "foo-1","value-2": {"id": "ran","other": "this"}}]
id-2
[{"value-1":"foo-1","value-2":{"id":"value1","other":"this"}},{"value-1":"foo-2","value-2":{"id":"value","other":"this"}}]
Which is to collect all columns for the grouped id and convert each row to json using column name as key and column value as the actual value.
You can use object_construct and array_agg within group to do this:
create or replace temp table T1 as
select
COLUMN1::string as id,
COLUMN2::string as "value-1",
COLUMN3::string as "value-2"
from (values
('id-1','test','{"id": "value","other": "this"}'),
('id-2','foo-1','{"id": "value","other": "this"}'),
('id-2','foo-2','{"id": "value1","other": "this"}')
);
select id
,array_agg(object_construct('value-1', "value-1", 'value-2', parse_json("value-2")))
within group (order by ID) as JSON_VALUE
from T1
group by ID
;
ID
JSON_VALUE
id-1
[ { "value-1": "test", "value-2": { "id": "value", "other": "this" } } ]
id-2
[ { "value-1": "foo-1", "value-2": { "id": "value", "other": "this" } }, { "value-1": "foo-2", "value-2": { "id": "value1", "other": "this" } } ]

How to compare a single array to a multidimensional array and get the field name from the multidimensional array in PHP?

Right now, I can get the driver id's in positions table in an array format and the employees data in employees table by using eloquent.
public function getDrivers() {
$driver_ids = Positions::where('name', '=', 'Driver')->pluck('id')->toArray();
$position_ids = Employees::all()->toArray();
return $driver_ids;
}
How can I get the first_name and last_name values from employees table if one of the $driver_ids matches the values from the position_id fields in employees table? Currently, the $position_ids gets all data from employees table.
I've tried using foreach's but can't get it right.
The $driver_ids returns this data in single array:
[
1,
6
]
While the $position_ids returns multidimensional array:
[
{
"id": 1,
"first_name": "Lyle",
"last_name": "Lucius",
"designation_id": [
2
],
"position_id": [
7,
9
],
"basic_pay": "784.00",
"cost_classification": "Indirect Labor",
"created_at": "2022-04-12T03:06:20.000000Z",
"updated_at": "2022-04-12T03:06:20.000000Z",
"deleted_at": null
},
{
"id": 2,
"first_name": "Shaeleigh",
"last_name": "Jesse",
"designation_id": [
2
],
"position_id": [
6
],
"basic_pay": "955.00",
"cost_classification": "Indirect Labor",
"created_at": "2022-04-12T06:38:31.000000Z",
"updated_at": "2022-04-12T06:38:31.000000Z",
"deleted_at": null
}
]
Any help is much appreciated.
Inside your getDrivers function try:
$driver_ids = Positions::where('name', '=', 'Driver')->pluck('id')->toArray();
$position_ids = Employees::whereIn('position_id', $driver_ids)->toArray();
return $driver_ids;
The whereIn method removes elements from the collection that do not have a specified item value that is contained within the given array. You can find the documentation in https://laravel.com/docs/9.x/collections#method-wherein

Postgresql get elements of a JSON array

Let's say that we have the following JSON in Postgresql:
{ "name": "John", "items": [ { "item_name": "lettuce", "price": 2.65, "units": "no" }, { "item_name": "ketchup", "price": 1.51, "units": "litres" } ] }
The JSONs are stored in the following table:
create table testy_response_p (
ID serial NOT NULL PRIMARY KEY,
content_json json NOT NULL
)
insert into testy_response_p (content_json) values (
'{ "name": "John", "items": [ { "item_name": "lettuce", "price": 2.65, "units": "no" }, { "item_name": "ketchup", "price": 1.51, "units": "litres" } ] }'
)
Since the following can return either JSON or text (with -> and ->> respectively select content_json ->> 'items' from testy_response_p) I want to use a subquery in order to get elements of the array under items:
select *
from json_array_elements(
select content_json ->> 'items' from testy_response_p
)
All I get is an error but I don't know what I'm doing wrong. The output of the subquery is text. The final output is:
{ "item_name": "lettuce", "price": 2.65, "units": "no" }
{ "item_name": "ketchup", "price": 1.51, "units": "litres" }
You need to join to the function's result. You can't use the ->> operator because that returns text, not json and json_array_elements() only works with a JSON value for its input.
select p.id, e.*
from testy_response_p p
cross join lateral json_array_elements(p.content_json -> 'items') as e;
Online example: https://rextester.com/MFGEA29396

Query for array elements inside JSON[] field array type

I have tried to unnest the JSON array with the function json_array_elements() and tried to count the elements of the array using json_array_length(field_name) not being successful. I am using PostgreSQL 9.4.5.
I was looking to query the result for the element "name" this is the data held on the json type array field crew:
[
{
"workHours": "9",
"workers": "50",
"checker_rate": 100,
"rate": 150,
"name": "Ramona",
"last": null,
"boxRate": 2,
"checkTraining": false,
"editing": true,
"ix": 0,
"breakPay": 3.0833333333333335,
"trainingPay": 0
},
{
"workHours": "4",
"workers": "50",
"checker_rate": 120,
"rate": 160,
"name": "Ramon",
"last": "Rosas",
"boxRate": 2,
"checkTraining": false,
"editing": false,
"id": 1,
"breakPay": 1.5416666666666667,
"trainingPay": 0
}
]
Your problem stems from the incorrect use of the type json[]. A json array is a single json object and its type is json, not json[]. Example:
create table test (id int, crew json);
insert into test values
(1, '
[
{
"workHours": "9",
"workers": "50",
"checker_rate": 100,
"rate": 150,
"name": "Ramona",
"last": null,
"boxRate": 2,
"checkTraining": false,
"editing": true,
"ix": 0,
"breakPay": 3.0833333333333335,
"trainingPay": 0
},
{
"workHours": "4",
"workers": "50",
"checker_rate": 120,
"rate": 160,
"name": "Ramon",
"last": "Rosas",
"boxRate": 2,
"checkTraining": false,
"editing": false,
"id": 1,
"breakPay": 1.5416666666666667,
"trainingPay": 0
}
]');
The function json_array_elements() works as expected:
select id, elem->'name' as name
from test
cross join json_array_elements(crew) elem;
id | name
----+----------
1 | "Ramona"
1 | "Ramon"
(2 rows)
One of the queries (or both) should work well with json[]:
select id, elem->'name' as name
from test
cross join json_array_elements(crew[1]) elem;
select id, elem->'name' as name
from test
cross join unnest(crew)
cross join json_array_elements(unnest) elem;

Solr field value in another query? is it possible?

I have this type of ouput genral
"docs": [
{
"id": "552e1acd5971b",
"product_id": "NOT05253",
"attribute_id": 0,
"attribute_name": "Brend",
"value_id": 12923,
"value_name": "ACER",
"category_id": 166,
"_version_": 1498504104368930800
},
{
"id": "552e1acd7d479",
"product_id": "NOT05604",
"attribute_id": 0,
"attribute_name": "Brend",
"value_id": 12923,
"value_name": "ACER",
"category_id": 166,
"_version_": 1498504104523071500
},
{
"id": "552e1acdc9c7c",
"product_id": "NOT05988",
"attribute_id": 0,
"attribute_name": "Brend",
"value_id": 12923,
"value_name": "ACER",
"category_id": 166,
"_version_": 1498504104851275800
},
{
"id": "552e1acdef261",
"product_id": "NOT06361",
"attribute_id": 0,
"attribute_name": "Brend",
"value_id": 12923,
"value_name": "ACER",
"category_id": 166,
"_version_": 1498504105011708000
}, .....
What I'm trying to do is getting results where product_id match at leas one product_id in another query...
category_id:166 AND value_id:12923
AND product_id:( _query_:"value_id:64 " )
I'm using this for making EAV product filtering faster, and this query particular has to shorten product_id count of ACER notebook in variation with 15.6" screen size :)
Another words - something like SQL query:
SELECT * FROM table WHERE value_id=12923 AND product_id IN (SELECT product_id FROM table WHERE value_id=64)
Any toughts? :D
Solr has some Join capabilities described here [1]. It could be what you're looking for.
About the other clauses: I would use a filter query (i.e. fq=value_id:12923)
[1] https://wiki.apache.org/solr/Join

Resources