Create an array from input array in PostgreSQL - sql

I am working on creating a PostgreSQL function. I have a situation where I receive an array as input and I want to use that array and get some other column for each element from that array and convert that into another array maintaining the same order. I have tried below, but I have some issues while executing it.
Below is the Example of what I need: (Let us say input_array is the input array to the function)
Example:
FOREACH item IN ARRAY $1
LOOP
tempVar = (select some_column from some_table where some_other_column = cast(item as varchar));
some_other_array := array_append(some_other_array, tempVar);
END LOOP;
But using the above approach I am not able to get the expected array as output. Somehow the values are not as expected with the above approach. And i am not able to debug whats going wrong in here as well as i cant see the Raise notices in console :(
Any other suggestions on this are highly appreciated.

Related

Finding smallest dtype to safely cast an array to

Let's say I want to find the smallest data type I can safely cast this array to, to save it as efficiently as possible. (The expected output is int8.)
arr = np.array([-101,125,6], dtype=np.int64)
The most logical solution seems something like
np.min_scalar_type(arr) # dtype('int64')
but that function doesn't work as expected for arrays. It just returns their original data type.
The next thing I tried is this:
np.promote_types(np.min_scalar_type(arr.min()), np.min_scalar_type(arr.max())) # dtype('int16')
but that still doesn't output the smallest possible data type.
What's a good way to achieve this?
Here's a working solution I wrote. It will only work for integers.
def smallest_dtype(arr):
arr_min = arr.min()
arr_max = arr.max()
for dtype_str in ["u1", "i1", "u2", "i2", "u4", "i4", "u8", "i8"]:
if (arr_min >= np.iinfo(np.dtype(dtype_str)).min) and (arr_max <= np.iinfo(np.dtype(dtype_str)).max):
return np.dtype(dtype_str)
This is close to your initial idea:
np.result_type(np.min_scalar_type(arr.min()), arr.max())
It will take the signed int8 from arr.min() if arr.max() fits inside of it.

Array contains string from column in Athena

I'm trying to check if at least one element of my_array array contains a string from my_column column in athena. I want the end result to be a boolean.
I've tried :
contains(my_array, my_column)
It seems to be partially working and I actually can't understand why because sometimes I get false even though the element of the array and the string are matching, but I never get true if there's no match.
So I've also tried (as seen here : Presto array contains an element that likes some pattern )
cardinality(filter(my_array, x->x like my_column))>0
But same issue, ending with the exact same result as above.
I thought I had an issue with some values from my_column, but after checking all my problematic values it appears the strings from my_column are clean.
For instance I am able to find a match for the first value of my_array, but no match for the second, although both values are in my_column.
Could someone please help ?
Thank you so much !!

Fetch Id of a selected data from a array of data

I have a list of array id but when I select any data I want the id of the selected data, I tried using map but it gives me a list of id's in a array. Please let me know how to do this, thanks in advance
Could you provide an example in order to understand your question better?
map() will always return an array, if you are getting an array with the desired value and a long list of undefined, then just add
.filter(e => e)
at the end.
If you want to iterate and obtain a single value, reduce() might be what you are looking for.

Searching each element of array using like

I would like some professional advice regarding my problem.
You see our database is using an ETL to retrieve massive data. Some or rather most of these data are aggregated.
Problem is I need to retrieve a data, base on the selected Stations
For example. I selected MNL.
Now, in aggregated column we have arrays like:
{MNL-CEB,CEB-MNL,DVO-MNL,MNL-DVO,DVO-CEB,CEB-DVO}
Now, given with my selected code (MNL), I should only be able to pick the following elements from the array.
MNL-CEB,
CEB-MNL,
DVO-MNL,
MNL-DVO
I've been trying various where conditions with no success. Hope you guys can help me out. Thanks!
Here's a piece of code I've been using below -
select distinct
unnest(fpd.segment_agg) segments
from daylightreport.f_dailysales_agg fpd
The data is too big to unnest, causing the script to load more.
Edit - I'm also using more than 1 station code. For instance
Where fpd.segment_agg IN ('MNL','CEB') or something similar to this.
Thanks in advance!
One way that avoids unnesting is to convert the array to a string then do a regex match on that string:
select *
from daylightreport.f_dailysales_agg fpd
where array_to_string(fpd.segment_agg, ',') ~ '(-){0,1}(MNL)(-){0,1}';
The regex makes sure the search string doesn't appear as part of another string. If that can't happen anyway, a simple like would probably do as well. This also assumes that the data never contains a ,
This is not going to be fast though, but avoids the unnesting in multiple rows.
Another option (although probably not really that much faster) is to write a function that loops through the array elements and uses the LIKE operator:
create or replace function any_element_like(p_elements text[], p_pattern text)
returns boolean
as
$$
declare
l_word text;
begin
foreach l_word in array p_elements
loop
if l_word like p_pattern then
return true;
end if;
end loop;
return false;
end;
$$
language plpgsql;
That could be used like this:
select *
from daylightreport.f_dailysales_agg fpd
where any_element_like(fpd.segment_agg, '%MNL%');

Golang server: send JSON with SQL query result that has variable number of columns

I'm creating a little implementation of RESTful API with Go server.
I'm extracting query parameters from URL (I know it's not safe, I'll try to fix this later on, but if you have any recommendations even on this topic, they would be helpful).
I have table name, desired columns and some conditions saved in 3 sring variables.
I'm using this query:
rows, _ := db.Query(fmt.Sprintf("SELECT %s FROM %s WHERE %s", columns, table, conditions))
I want to send the query result back to my frontend, as JSON. I have variable number of unknown columns, so I can't do it "standard" way.
One solution I can think of is to build a JSON string "manually" from from query result and rows.Columns().
But I'd like to do this in a more sofisticated way using something like variadic interface and stuff like that. The problem is, even after trying a lot, I still dont understand how it works.
I tried using following code
cols, err := rows.Columns() // Get the column names; remember to check err
vals := make([]sql.RawBytes, len(cols)) // Allocate enough values
ints := make([]interface{}, len(cols)) // Make a slice of []interface{}
for i := range ints {
vals[i] = &ints[i] // Copy references into the slice
}
for rows.Next() {
err := rows.Scan(vals...)
// Now you can check each element of vals for nil-ness,
// and you can use type introspection and type assertions
// to fetch the column into a typed variable.
}
from this tutorial but it doesn't work, I'm getting errors like
cannot use &ints[i] (type *interface {}) as type sql.RawBytes in assignment
And even if it'd work, I dont understand it.
Does anyone have a good solution for this? Some explanation would be great aswell.
Thanks a lot.
The first problem is here:
for i := range ints {
vals[i] = &ints[i] // Copy references into the slice
}
This is you setting values that are meant to be RawBytes as pointers to interfaces.
Before I explain what that's meant to be doing I'll see if I can explain what the general idea is here.
So normally when getting the response from SQL in Go you'd have a slice with each column and type (id int, name string, ...) so you can then read each SQL record into this slice and each column will be mapped to the value of the same type.
For cases like yours where you will have more variety in the response from SQL and need Go to handle it, you'd do this:
for i := range ints {
ints[i] = &vals[i] // Copy references into the slice
}
What this is saying is each of your interface values holds a pointer to the vals array that will hold the response from SQL. (In my examples I use [][]byte instead of RawBytes so value in vals would be a slice of byte values from SQL.)
You'd then do:
err := rows.Scan(ints...)
Since interface can evaluate to any type, when the ints array becomes populated it will accept any value then update the position in vals array based on the pointer with the value from SQL as a RawBytes type.
HTH