I have two tables, one of them is a main table and the other is the decode. The decode has 142 rows and 2 columns. Cause of death code and description. The main table has person information and the reason of death and secondary reason of death.
Decode table
code
description
1
infection
2
covid
main table
client
reason_1
reason_2
01
1
null
02
2
1
03
1
2
Expected table
client
reason_1
reason_2
reason_1_desc
reason_2_desc
01
1
null
infection
null
02
2
1
covid
infection
03
1
2
infection
covid
How can I get this output without typing in all the values from decode table and using decode function or subquery factoring?
Join the description table twice (for each of two reasons):
Sample data:
SQL> with
2 t_decode (code, description) as
3 (select 1, 'infection' from dual union all
4 select 2, 'covid' from dual
5 ),
6 t_main (client, reason, reason_2) as
7 (select '01', 1, null from dual union all
8 select '02', 2, 1 from dual union all
9 select '03', 1, 2 from dual
10 )
Query:
11 select m.client, m.reason, m.reason_2,
12 d1.description reason_desc,
13 d2.description reason_2_desc
14 from t_main m left join t_decode d1 on d1.code = m.reason
15 left join t_decode d2 on d2.code = m.reason_2
16 order by m.client;
CL REASON REASON_2 REASON_DE REASON_2_
-- ---------- ---------- --------- ---------
01 1 infection
02 2 1 covid infection
03 1 2 infection covid
SQL>
Related
Im trying to extract the following information from the oracle table below: A list of all the unique pairwise Status combinations for entries and their referenced entries. Entries with no referenced entry will be ignored. For example, for the entry 10 I expect the output to be (1,3) because its status is 1 and the status of the referenced entry 7 is 3. If the list doesn't already have this combination, it should be added to the list. Can anyone guide me in the right direction? I'm totally clueless as to how to even google what I want to achieve.
EDIT: The first column is the ID of the entry, the second column is the status of the entry, and the third column is the ID of another entry in the same table that is referenced.
Looks like a self join:
Sample data:
SQL> with test (id, status, ref_id) as
2 (select 1, 0, null from dual union all
3 select 2, 1, 3 from dual union all
4 select 3, 3, null from dual union all
5 select 4, 6, 6 from dual union all
6 select 5, 0, 1 from dual union all
7 select 6, 4, null from dual union all
8 select 7, 3, null from dual union all
9 select 8, 5, 9 from dual union all
10 select 9, 2, null from dual union all
11 select 10, 1, 7 from dual
12 )
Query:
13 select a.id, a.status, b.status
14 from test a join test b on b.id = a.ref_id
15 where a.ref_id is not null
16 order by a.id;
ID STATUS STATUS
---------- ---------- ----------
2 1 3
4 6 4
5 0 0
8 5 2
10 1 3
SQL>
If you want to get distinct pairs (but still know IDs involved), you could use listagg (it'll work as long as resulting string doesn't exceed 4000 characters; if it does, use xmlagg instead):
13 select listagg(a.id, ', ') within group (order by a.id) id,
14 a.status, b.status
15 from test a join test b on b.id = a.ref_id
16 where a.ref_id is not null
17 group by a.status, b.status
18 order by id;
ID STATUS STATUS
-------------------- ---------- ----------
2, 10 1 3
4 6 4
5 0 0
8 5 2
SQL>
If you don't care about IDs, then
13 select distinct a.status, b.status
14 from test a join test b on b.id = a.ref_id
15 where a.ref_id is not null
16 order by a.status, b.status;
STATUS STATUS
---------- ----------
0 0
1 3
5 2
6 4
SQL>
I have a query which as follows:
select c.* from cases c
left outer join (select case_id, case_status_id from case_status where case_id not in (SELECT case_id
FROM case_status
where (case_status_id = 16 and case_status_date < sysdate - 365))) cs ON cs.case_id = c.case_id
left outer join lkp_case_status lkp_cs
on lkp_cs.id = cs.case_status_id
where c.case_type = 'P'
and c.delete_date is null
The 2nd line used to be a join earlier but now I had to convert it to left outer join. What it does is it checks for case status and if the case status is 16 and the date is a year back don't show the record. When I change it to left outer join it picks up the record even when the dates are in 2019.
case
id name
1 AAA
2 BBB
3 CCC
4 DDD
case_status
1 16 01-NOV-19 03.42.37.420000000 PM
1 5 01-NOV-19 03.42.37.420000000 PM
2 1 18-NOV-19 12.36.11.268000000 PM
2 3 18-NOV-19 12.36.11.268000000 PM
3 5 18-NOV-21 12.36.11.268000000 PM
3 16 18-NOV-21 12.36.11.268000000 PM
The output should show as follows:
Result:
id name status
2 BBB 1,3
3 CCC 5,16
4 DDD
case id 1 has status 16 and dates back to 2019, case id 3 though has status 16 is within a year so should be picked up.
The query is really big but I am missing only this case status scenario hence posting a part of it.
Any suggestions or inputs, please.
How about not exists?
Sample data:
SQL> with
2 tcase (id, name) as
3 (select 1, 'AAA' from dual union all
4 select 2, 'BBB' from dual union all
5 select 3, 'CCC' from dual union all
6 select 4, 'DDD' from dual
7 ),
8 tcase_status (case_id, case_status_id, case_status_date) as
9 (select 1, 16, date '2019-11-01' from dual union all
10 select 1, 5, date '2019-11-01' from dual union all
11 select 2, 1, date '2019-11-18' from dual union all
12 select 2, 3, date '2019-11-18' from dual union all
13 select 3, 5, date '2021-11-18' from dual union all
14 select 3, 16, date '2021-11-18' from dual
15 )
Query:
16 select c.id,
17 c.name,
18 listagg(cs.case_status_id, ', ') within group (order by cs.case_status_id) status
19 from tcase c left join tcase_status cs on c.id = cs.case_id
20 where not exists (select null
21 from tcase_status c
22 where c.case_id = cs.case_id
23 and c.case_status_id = 16
24 and c.case_status_date < add_months(trunc(sysdate), -12)
25 )
26 group by c.id, c.name
27 order by c.id;
ID NAME STATUS
---------- ---- ----------
2 BBB 1, 3
3 CCC 5, 16
4 DDD
SQL>
I am trying to count the number of rows under specific "header rows" - for example, I have a table that looks like this:
Row # | Description | Repair_Code | Data Type
1 | FRONT LAMP | (null) | Header
2 | left head lamp | 1235 | Database
3 | right head lamp | 1236 | Database
4 | ROOF | (null) | Header
5 | headliner | 1567 | Database
6 | WHEELS | (null) | Header
7 | right wheel | 1145 | Database
Rows 1, 4 and 6 are header rows (categories) and the others are descriptors under each of those categories. The Data Type column denotes if the row is a header or not.
I want to be able to count the number of rows under the header rows to return something that looks like:
Header | Occurrences
FRONT LAMP | 2
ROOF | 1
WHEELS | 1
Thank you for the help!
Data model looks wrong. If that's some kind of a hierarchy, table should have yet another column which represents a "parent row#".
The way it is now, it's kind of questionable whether you can - or can not - do what you wanted. The only thing you can rely on is row#, which is sequential in your example. If that's not the case, then you have a problem.
So: if you use a lead analytic function for all header rows, then you could do something like this (sample data in rows #1 - 7; query that might help begins at line #8):
SQL> with test (rn, description, code) as
2 (select 1, 'front lamp' , null from dual union all
3 select 2, 'left head lamp' , 1235 from dual union all
4 select 3, 'right head lamp', 1236 from dual union all
5 select 4, 'roof' , null from dual union all
6 select 5, 'headliner' , 1567 from dual
7 ),
8 hdr as
9 -- header rows
10 (select rn,
11 description,
12 lead(rn) over (order by rn) next_rn
13 from test
14 where code is null
15 )
16 select h.description,
17 count(*)
18 from hdr h join test t on t.rn > h.rn
19 and (t.rn < h.next_rn or h.next_rn is null)
20 group by h.description;
DESCRIPTION COUNT(*)
--------------- ----------
front lamp 2
roof 1
SQL>
If data model was different (note parent_rn column), then you wouldn't depend on sequential row# values, but
SQL> with test (rn, description, code, parent_rn) as
2 (select 0, 'items' , null, null from dual union all
3 select 1, 'front lamp' , null, 0 from dual union all
4 select 2, 'left head lamp' , 1235, 1 from dual union all
5 select 3, 'right head lamp', 1236, 1 from dual union all
6 select 4, 'roof' , null, 0 from dual union all
7 select 5, 'headliner' , 1567, 4 from dual
8 ),
9 calc as
10 (select parent_rn,
11 sum(case when code is null then 0 else 1 end) cnt
12 from test
13 connect by prior rn = parent_rn
14 start with parent_rn is null
15 group by parent_rn
16 )
17 select t.description,
18 c.cnt
19 from test t join calc c on c.parent_rn = t.rn
20 where nvl(c.parent_rn, 0) <> 0;
DESCRIPTION CNT
--------------- ----------
front lamp 2
roof 1
SQL>
I would approach this using window functions. Assign a group to each header by doing a cumulative count of the NULL values of repair_code. Then aggregate:
select max(case when repair_code is null then description end) as description,
count(repair_code) as cnt
from (select t.*,
sum(case when repair_code is null then 1 else 0 end) over (order by row#) as grp
from t
) t
group by grp
order by min(row#);
Here is a db<>fiddle.
Given a list of client names (comma separated) I need to find out how many exists in Client table and how many dont.
The table and input lists are both huge; here I'm just giving table as an example of my requirement.
Client
client_name
status
abc
1
def
1
ghi
0
jkl
1
Query I thought of using is
select client_name, count(client_name) over (partition by client_name) count_client from client where status = 1 and client_name in ('abc', 'xyz', 'ghi', 'jkl');
This returns:
client_name
count_client
abc
1
jkl
1
But what I need is
client_name
count_client
abc
1
xyz
0
ghi
0
jkl
1
Could someone please help me with the SQL query
If you have "huge" amount of data, then your best option is to store list of values you're interested in into a separate table. That's trivial.
Otherwise, as an alternative you could try something like this (sample data in lines #1 - 11; query begins at line #12):
SQL> WITH
2 client (client_name, status)
3 AS
4 -- this is contents of your table
5 (SELECT 'abc', 1 FROM DUAL
6 UNION ALL
7 SELECT 'def', 1 FROM DUAL
8 UNION ALL
9 SELECT 'ghi', 0 FROM DUAL
10 UNION ALL
11 SELECT 'jkl', 1 FROM DUAL)
12 -- join your table with a collection
13 SELECT t.COLUMN_VALUE AS client_name, NVL (SUM (c.status), 0) AS count_client
14 FROM client c
15 RIGHT JOIN TABLE (sys.odcivarchar2list ('abc',
16 'xyz',
17 'ghi',
18 'jkl')) t
19 ON t.COLUMN_VALUE = c.client_name
20 AND c.status = 1
21 GROUP BY t.COLUMN_VALUE
22 ORDER BY t.COLUMN_VALUE;
CLIENT_NAME COUNT_CLIENT
--------------- ------------
abc 1
ghi 0
jkl 1
xyz 0
SQL>
You should ideally maintain a separate table containing the client names of interest. Absent that, we can use a CTE to store the values, then left join to your current table:
WITH clients AS (
SELECT 'abc' AS client_name FROM dual UNION ALL
SELECT 'xyz' FROM dual UNION ALL
SELECT 'ghi' FROM dual UNION ALL
SELECT 'jkl' FROM dual
)
SELECT cl.client_name, COUNT(c.client_name) AS count_client
FROM clients cl
LEFT JOIN client c
ON c.client_name = cl.client_name AND
c.status = 1
GROUP BY cl.client_name;
Demo
I have table in which one of the columns is having 1000s of records out which most of them are duplicates. Finding duplicates are easy but in this situation, they are partial duplicates e.g
ID NAME Status
1 abc Capital Approved
2 (abc Capital) Terminated
3 abc capital (dupe) Null
4 abc capitalx Null
5 BT Capital Approved
6 XE Capital Approved
7 xyz Finance Approved
8 xyz Finance X Null
9 xyz finance dupe Null
So from the above data, I want to retrieve duplicate names which are partially duplicate E.g
output:
1 abc Capital Approved
2 (abc Capital) Terminated
3 abc capital (dupe) Null
4 abc capitalx Null
5 xyz Finance Approved
6 xyz Finance X Null
7 xyz finance dupe Null
One option might be to use UTL_MATCH package and one of its functions. I chose edit_distance_similarity for this demonstration, but you might pick another.
SQL> with test (id, name) as
2 (select 1, 'abc Capital' from dual union all
3 select 2, '(abc Capital)' from dual union all
4 select 3, 'abc capital (dupe)' from dual union all
5 select 4, 'abc capitalx' from dual union all
6 select 5, 'BT Capital' from dual union all
7 select 6, 'XE Capital' from dual union all
8 select 7, 'xyz Finance' from dual union all
9 select 8, 'xyz Finance X' from dual union all
10 select 9, 'xyz finance dupe' from dual
11 ),
12 simil as
13 (select a.id, a.name aname, b.name bname,
14 utl_match.edit_distance_similarity(a.name, b.name) simil
15 from test a cross join test b
16 )
17 select distinct id, aname as name
18 from simil
19 where aname <> bname
20 and simil > 80
21 order by id;
ID NAME
---------- ------------------
1 abc Capital
2 (abc Capital)
4 abc capitalx
7 xyz Finance
8 xyz Finance X
SQL>