Selecting a row by searching a specific value in an Array column - postgresql

We have a table where one of the columns is an array. I need to select a row or many rows as long as my search value matches their values using ILIKE. My problem is that I need to search the values of an array column as well. I tried using ANY but the value needs to be exact to select a row. I need something similar to ILIKE but for that array column.
Thank you in advance.

Use unnest function:
SELECT x.value
FROM my_table t, unnest(t.my_array_column) as x(value)
WHERE x.value ILIKE 'foo'
Once your question is also tagged elixir, for converting this to Ecto use Ecto.Query.API.fragment/1 for the select condition and Ecto.Query.API.ilike/2 for match.

Related

How to hash a query result with sha256 in PostgreSQL?

I want to somehow hash the result of a query in PostgreSQL. I have a query like
SELECT output FROM result;
And it returns a column composed only of integers. So I somehow want to hash the result of this query. Concatenate the values and hash, or somehow hash the query output directly. Simply I need a way to put it inside SELECT sha256(...). So please note that I do not want to get hash of every column entry, but one hash that somehow corresponds to the query output. Any ideas?
PostgreSQL doesn't come with a built-in streaming hash function exposed to the user, so the easiest way is to build the string in memory and then hash it. Of course this won't work with giant result sets. You can use digest from the pg_crypto extension. You also need to order your rows, or else you might get different results on the same data from one execution to the next if you get the rows in different orders.
select digest(string_agg(output::text,' ' order by output),'sha256')
from result;
Replace 1234 with your column name and add [from table_name] to this query:
select encode(digest(1234::text, 'sha256'), 'hex')
Or for multiple rows use this:
select encode(
digest(
(select array_agg(q1)::text[] from (select row(R.*)::text as q1 from (SELECT output FROM result)R)alias)::text
, 'sha256')
, 'hex')

Postgresql parse string values to integers

Is there a way in Postgres I can parse string values to integers? Basically I'm trying to query one table (let's call it table_one) using values from another table (table_two) in a character varying column.
Say SELECT char_column FROM table_two results in "2,4,6,8", I'd like to use this result in a second query as;
SELECT column FROM table_one WHERE some_id IN (2,4,6,8)
How can I get the string "2,4,6,8" to values 2,4,6,8 so as to be able to use it in the second query?
I've tried casting and to_number functions to no success.
SELECT column
FROM table
WHERE other_column = ANY(string_to_array('2,4,6,8', ',')::INT[])
Please try this:
SELECT column FROM table WHERE other_column IN (
SELECT NULLIF(i,'')::int
FROM regexp_split_to_tables('2,4,6,8',',') t(i)
)
Explanation:
The part regexp_split_to_tables('2,4,6,8',',') will split the string into a table. Then you cast it into integer.
Hopefully it will help you.

Why array_agg() is returning empty array in postgresql?

I have an integer type column named as start. I want to make an array by the values of this column. It seemed to be very easy and I used array_agg(), but it is giving empty array as output. Following is my column data
start
1
2
11
5
.
.
. (and so on)
And following is my query used to make the array:
select array_agg(start) as start_array from table1;
Why is it giving empty array?
It's not
There is no way that this can return empty unless there are no rows. Perhaps a JOIN or a WHERE clause is wrong and you have 0-rows?
Also as a micro-optimization if your query is this simple,
select array_agg(start) as start_array from table1;
Then it's probably better written with the ARRAY() constructor...
SELECT ARRAY(SELECT start FROM table1) AS start_array;

PostgreSQL use function result in ORDER BY

Is there a way to use the results of a function call in the order by clause?
My current attempt (I've also tried some slight variations).
SELECT it.item_type_id, it.asset_tag, split_part(it.asset_tag, 'ASSET', 2)::INT as tag_num
FROM serials.item_types it
WHERE it.asset_tag LIKE 'ASSET%'
ORDER BY split_part(it.asset_tag, 'ASSET', 2)::INT;
While my general assumption is that this can't be done, I wanted to know if there was a way to accomplish this that I wasn't thinking of.
EDIT: The query above gives the following error [22P02] ERROR: invalid input syntax for integer: "******"
Your query is generally OK, the problem is that for some row the result of split_part(it.asset_tag, 'ASSET', 2) is the string ******. And that string cannot be cast to an integer.
You may want to remove the order by and the cast in the select list and add a where split_part(it.asset_tag, 'ASSET', 2) = '******', for instance, to narrow down that data issue.
Once that is resolved, having such a function in the order by list is perfectly fine. The quoted section of the documentation in the comments on the question is referring to applying an order by clause to the results of UNION, INTERSECTION, etc. queries. In other words, the order by found in this query:
(select column1 as result_column1 from table1
union
select column2 from table 2)
order by result_column1
can only refer to the accumulated result columns, not to expressions on individual rows.

Create an index for json_array_elements in PostgreSQL

I need to create an index from a query that uses json_array_elements()
SELECT *, json_array_elements(nested_json_as_text::json) as elements FROM my_table
Since the json contains multiple elements, the result is that the original index is now duplicated across rows and no longer unique.
I am not very familiar with creating indices and want to avoid doing anything destructive. What is the best way to create a column of unique integers for this case?
Found an answer:
SELECT *, json_array_elements(nested_json_as_text::json) as elements, row_number() over () as my_index FROM my_table