PostgreSQL: Search by reference field value - postgresql

Currently, I have two tables named users and posts. Ever posts row includes a userId as reference and now I want to run query to search by userId array.
select * from posts where 'userId' = ANY(ARRAY['9', '77']);
And posts table looks like:
id userId text
1 9 text1
2 77 text2
The query returns empty while it returns full list if I remove where section. I guess the problem is that userId is a reference value but not sure how I can fix this problem.

Single quotes denote string literals. 'userId' is the userId column, but a string literal. Likewise, assuming you IDs are numbers, you should remove the quotes to get numeric literals instead of string literals:
select * from posts where userId = ANY(ARRAY[9, 77]);
-- No quotes -------------^----^-------------^--^^

Perhaps this works:
select * from posts where userId in (9,77);

Related

Postgres: ANY function does not work on varchar array

I have a "product" table with a varchar[] column to keep excluded companies.
When I select the array for a specific product, I get it like this:
SELECT excluded_company_codes FROM product WHERE code = '123'
excluded_company_codes
----------
{'10'}
However, oddly enough, when I try to check if company code exists in the array with ANY function, it doesn't work:
SELECT '10'=ANY(product.excluded_company_codes) where code = '123'
?column?
----------
false
What am I doing wrong here?
The string in the array contains two single quotes. If you want to find that, you have to
SELECT '''10''' = ANY(product.excluded_company_codes)
FROM product
WHERE code = '123';
If you want to avoid doubling the quotes, you can use dollar quoting: $$'10'$$.

PostgreSQL - How to match a value in a table where column has values with comma separation

I have a table with the following field values:
I want to do a select where I can match a value from this keyword column. For example:
SELECT templateid FROM public.templates WHERE keyword='Yes'
I don't want to use LIKE because in the case one of the comma-separated values is Yessy then I will get a return and that's not correct.
It has to be an exact match of one of the comma separated values.
Any clue?
You can convert the string into an array:
SELECT templateid
FROM public.templates
WHERE 'Yes' = any(string_to_array(keyword, ','))

Select rows in postgres table where an array field contains NULL

Our system uses postgres for its database.
We have queries that can select rows from a database table where an array field in the table contains a specific value, e.g.:
Find which employee manages the employee with ID 123.
staff_managed_ids is a postgres array field containing an array of the employees that THIS employee manages.
This query works as expected:
select *
from employees
where 123=any(staff_managed_ids)
We now need to query where an array field contains a postgres NULL. We tried the following query, but it doesn't work:
select *
from employees
where NULL=any(staff_managed_ids)
We know the staff_managed_ids array field contains NULLs from other queries.
Are we using NULL wrongly?
NULL can not be compared using =. The only operators that work with that are IS NULL and IS NOT NULL.
To check for nulls, you need to unnest the elements:
select e.*
from employees e
where exists (select *
from unnest(e.staff_managed_ids) as x(staff_id)
where x.staff_id is null);
if all your id values are positive, you could write something like this:
select *
from employees
where (-1 < all(staff_managed_ids)) is null;
how this works is that -1 should be less than all values, however comparison with null will make the whole array comparison expression null.

postgresql update a table column based on values stored in another table

I have two tables. I want to update the emodnet_code column values of the table named 2018_01 based on the column emodnet_type of another table named shiptype_emodnet and using the matching of values of two other columns: column aisshiptype from 2018_01 table and column aisshiptype from shyptype_emodnet table. Query returned successfully but 0 rows affected:
UPDATE "2018_01"
SET emodnet_code = shiptype_emodnet.emodnet_type
FROM "shiptype_emodnet"
WHERE '2018_01.aisshiptype' = 'shiptype_emodnet.aisshiptype';
You are comparing string constants in your WHERE clause, not columns. So your where clause:
WHERE '2018_01.aisshiptype' = 'shiptype_emodnet.aisshiptype';
is always false, because the string literal '2018_01.aisshiptype' is never the same as the string literal 'shiptype_emodnet.aisshiptype'. So your where condition is essentially the same as:
where false
Identifiers need to be quoted with double quotes ("). Single quotes (') are only for string literals.
UPDATE "2018_01"
SET emodnet_code = shiptype_emodnet.emodnet_type
FROM "shiptype_emodnet"
WHERE "2018_01".aisshiptype = shiptype_emodnet.aisshiptype;
And you only need the double quotes for columns or tables that use names that are illegal in SQL or were created using double quotes and mixed case.
Can you try:
UPDATE "2018_01" t
SET t.emodnet_code = (SELECT shiptype_emodnet.emodnet_type
FROM shiptype_emodnet
WHERE t.aisshiptype = shiptype_emodnet.aisshiptype
Limit 1);
You should add limit 1 for update each row

AR Query for jsonb attribute column

I'm using Postgres for my db, and I have a column in my Auction model as a jsonb column. I want to create a query that searches the Auction's json column to see whether a user's name OR email exists in any Auction instance's json column.
Right now I have #auctions = Auction.where('invitees #> ?', {current_user.name.downcase => current_user.email.downcase}.to_json), but that only brings back exact key => value matches I want to know whether the name OR the email exists.
You're using the #> operator. The description for it is this:
“Does the left JSON value contain the right JSON path/value entries
at the top level?”
You probably want the ? operator if you want to return a row when the key (name in your case) matches.
There's not a good way to search for values only in a JSON column (see this answer for more details), but you could check if the key exists alone or the key and value match exists.
The same ActiveRecord methods and chaining apply as when using non-JSON columns, namely where and where(…).or(where(…)):
class Auction
def self.by_invitee(user)
name = user.name.downcase
json = { name => user.email } # note: you should be downcasing emails anyways
where('invitee ? :name', name: name).or(
where('invitee #> :json', json: json)
)
end
end
This is just a temporary patch until I add an Invite model, but casting the invitee column to text I can search the columns. Like so
SELECT * FROM auctions
WHERE data::text LIKE "%#{string I'm searching for}%"
So, AR:
Auction.where('data::text LIKE ?', "%#{string I'm searching for}%")