Home > Net >  Postgresql - How to use string_to_array on another column value
Postgresql - How to use string_to_array on another column value

Time:06-09

How can I use string_to_array or split_part on another column value.

I want do something like select * from tenants where id IN (select string_to_array(select ancestry from tenants where id = 39,'/'));

-[ RECORD 1 ]------------- ----------------------
id                        | 1
domain                    |
subdomain                 |
name                      | My Company
login_text                |
logo_file_name            |
logo_content_type         |
logo_file_size            |
logo_updated_at           |
login_logo_file_name      |
login_logo_content_type   |
login_logo_file_size      |
login_logo_updated_at     |
ancestry                  |
divisible                 | t
description               | Tenant for My Company
use_config_for_attributes | t
default_miq_group_id      | 1
source_type               |
source_id                 |
-[ RECORD 3 ]------------- ----------------------
id                        | 35
domain                    |
subdomain                 |
name                      | Tenant_2
login_text                |
logo_file_name            |
logo_content_type         |
logo_file_size            |
logo_updated_at           |
login_logo_file_name      |
login_logo_content_type   |
login_logo_file_size      |
login_logo_updated_at     |
ancestry                  | 1
divisible                 | t
description               | Tenant_2
use_config_for_attributes | f
default_miq_group_id      | 36
source_type               |
source_id                 |
-[ RECORD 7 ]------------- ----------------------
id                        | 39
domain                    |
subdomain                 |
name                      | Child_Teanant_202
login_text                |
logo_file_name            |
logo_content_type         |
logo_file_size            |
logo_updated_at           |
login_logo_file_name      |
login_logo_content_type   |
login_logo_file_size      |
login_logo_updated_at     |
ancestry                  | 1/35
divisible                 | t
description               | Child_Teanant_202
use_config_for_attributes | f
default_miq_group_id      | 52
source_type               |
source_id                 |

CodePudding user response:

Use regex to enforce word boundaries:

select *
from tenants
where (select ancestry from tenants where id = 39) 
  ~ ('\y' || id || '\y')

See live demo.

Without the word boundaries an id of 1 would match an ancestry of 123.

Note Postgres's unusual regex for word boundary \y, which elsewhere is \b.

CodePudding user response:

There are two ways to solve this.

One is to simply unnest the elements of ancestry

select *
from tenants
where id in (select a.id::int
             from tenants t2
                cross join unnest(string_to_array(t2.ancestry, '/')) as a(id)
             where t2.id = 39);

Converting the string to an array in order to be able to use the = ANY() operator is a bit tricky, because you need two levels of parentheses plus a type cast to an integer array to make that work:

select *
from tenants
where id = any ((select string_to_array(t2.ancestry, '/')
                 from tenants t2
                 where t2.id = 39)::int[]);
             

Online example

  • Related