Reputation: 2229
Please refer SQL Oracle : how to find records maching a particular id in the column
Now my query is on the similar lines:
My table has the following data:
now I want to find the records that have asso_entity_id as a combination of 3 values. For eg:- if I select asso_entities from my jsp as 30000, 30001 and 80002 (in any order), I should get the first record of the above table.
Upvotes: 2
Views: 304
Reputation: 5792
A bit simplified version of techdo's example:
This is the test table structure:
ID DATASET_NAME DATASET_VAL
------------------------------------------
1 DATASET1 3000 | 30001 | 80002
2 DATASET1 3000 | 80002
3 DATASET1 3000 | 80002
SELECT LISTAGG(str, ' | ') WITHIN GROUP (ORDER BY str) asso_ety_id
FROM
(
SELECT DISTINCT id, dataset_name
, TRIM(REGEXP_SUBSTR (dataset_val, '[^|]+', 1, LEVEL)) str
FROM your_tab
CONNECT BY LEVEL <= LENGTH(REGEXP_REPLACE(dataset_val, '[^|]+')) + 1
)
WHERE str IN ('80002', '30001', '3000') -- in any order --
-- AND id = 1 -- optional --
/
Output:
3000 | 30001 | 80002
Upvotes: 0
Reputation: 191305
Following on from my answer on your previous question, and continuing to use that as an example becuase I can see the underlying query that's doing the listagg
... you can match on multiple values, count how many you matched on, and apply a further filter to ensure you matched on all of them. Something like:
select distinct role_id, role_name, active, companyName, permission_id,
permission_name, rn, total_rows, roleCreated
from (
select t.*,
count(raw_permission_id) over (partition by role_id) as cnt
from (
select r.role_id,
r.role_name,
r.active,
decode(r.entity_type_id, 1000, m.name, 3000, cour.name,
4000, 'Ensenda') companyName,
p.permission_id as raw_permission_id,
listagg(p.permission_id, ' | ')
within group (order by p.permission_id)
over (partition by r.role_id) permission_id,
listagg(p.permission_name, ' | ')
within group (order by p.permission_id)
over (partition by r.role_id) permission_name,
dense_rank() over (order by r.created_ts desc) as rn,
count(distinct r.role_id) over () as total_rows,
r.created_ts roleCreated
from t_role r
left join t_role_permission rp ON r.role_id = rp.role_id
left join t_permission p ON rp.permission_id = p.permission_id
left join merchant m on r.entity_id = m.merchantkey
left join courier cour on r.entity_id = cour.courierkey
) t
where raw_permission_id in (301446, 301445)
)
where cnt = 2
and rn between 1 and 100
order by roleCreated desc;
The only difference from that previous answer is the outer two layers of the query:
select ...
from (
select t.*,
count(raw_permission_id) over (partition by role_id) as cnt
from (
... -- no changes here
) t
where raw_permission_id in (301446, 301445)
)
where cnt = 2
...
So it's now looking for two possible permissions, and counting - analytically, so for each role - how many were matched. The outer query checks that the number that matched is 2, which you'll obviously have to adjust depending on how many options you're trying to match against.
For this question it would add something like:
count(raw_asso_entity_id) over (partition by <some_id>) as cnt
...
where raw_asso_id in (30000, 30001 and 80002)
...
where cnt = 3
Upvotes: 0
Reputation: 18649
Please check the query... Bit long... will try to shorten it.
with test as (
select * from YOURTABLE
)
SELECT distinct DATASETNAME FROM(
select x.*, COUNT(*) OVER (partition by DATASETNAME ORDER BY DATASETNAME) CNT From(
select DATASETNAME, regexp_substr (ASSO_ENTITY_ID, '[^|]+', 1, row_number() OVER (partition by DATASETNAME ORDER BY DATASETNAME)) split
from test
connect by level <= length (regexp_replace (ASSO_ENTITY_ID, '[^|]+')) + 1
)x where SPLIT IS NOT NULL
)xx
WHERE SPLIT IN ('300000', '300001', '800002') AND
CNT =3;
Upvotes: 1