Update an Oracle table using listagg statement on the same table - oracle

I have a table that contains one or more records for each item. Each item can contain multiple sub-items (boards) and so the Itemid is often replicated with each record showing the division category (a number) that the Item/sub-item combo resides in:
ItemId Board# Division
142585109 0 6
142585114 0 3
142585116 0 1
142585120 0 4
142585197 0 5
142585197 2 4
142585197 3 3
142585197 5 6
142585197 8 1
142585294 0 4
142585317 0 1
I want to update the table and aggregate all of the division values (as a comma separated string) in a new field in this table, something like:
ItemId Board# AggDivisions
142585109 0 6
142585114 0 3
142585116 0 1
142585120 0 4
142585197 0 1,3,4,5,6
142585294 0 4
142585317 0 1
I used a ListAgg query to do the aggregation which works correctly but when I tried to incorporate this into an update query, I end up with multiple duplicates in the aggregated field for each record.
Here is my update attempt:
update itemtable dd
set aggregateddivisions = (SELECT Listagg(division, ',') within GROUP (ORDER BY division)
FROM itemtable ev
WHERE ev.itemid = dd.itemid
)
where exists (select 1
from itemtable ev
where ev.itemid = dd.itemid
);
How can I update the table with the aggregated list of values from the same table without ending up with duplicates?

Related

Count rows from 1 table that have more than x rows in another table

I have 3 tables - Folders, Documents & Versions
FolderID
Folder Name
1
Folder 1
2
Folder 2
3
Folder 3
Documents looks like this:
DocID
Doc Name
FolderID
1000
Doc 1
1
1001
Doc 2
1
1002
Doc 3
2
1003
Doc 4
2
1004
Doc 5
3
Versions looks like this:
VersionID
DocID
1
1000
2
1001
3
1001
4
1002
5
1003
6
1003
7
1004
So Doc 1, 3 & 5 have 1 version each, and Doc 2 & 4 have 2 versions.
I would like to count the documents that have more than 1 version. In this example Folder 1 & 2 both have 1 document with more than 1 version, and Folder 3 has none.
I'd like some DAX that will accomplish that. I'm managing to confuse myself because the filter is based on a count of a related table.
This is what I came up with, but I know I'm off
Count Docs =
VAR VersionsMin = 2
RETURN
CALCULATE (
COUNT ( 'Documents'[DocID] ),
FILTER ( 'Versions', COUNT ( 'Versions'[VersionID] ) >= VersionsMin )
)
Try this out:
In the first step add a new column to your Documents table
Version Count =
COUNTROWS(RELATEDTABLE(Versions))
In the second step you can use this column for filtering
Docs with multiple versions =
CALCULATE(
COUNT(Documents[DocID]),
Documents[Version Count] > 1
)
This allows you to create the following table visual:

Hierarchical query get all children as rows

Data:
ID PARENT_ID
1 [null]
2 1
3 1
4 2
Desired result:
ID CHILD_AT_ANY_LEVEL
1 2
1 3
1 4
2 4
I've tried SYS_CONNECT_BY_PATH, but I don't understand how to convert it result into "inline view" which I can use for JOIN with main table.
select connect_by_root(id) id, id child_at_any_level
from table
where level <> 1
connect by prior id = parent_id;

Hive Query array as field

I have two Hive table :
Client Table :
id,name,salary
1 ,John, 10000
2 ,Melissa, 5000
Account Table :
id,account_number,client_id
1 ,00920202, 1
2 ,00920203, 1
3 ,00920204, 1
4 ,00920205, 2
5 ,00920206, 2
I need a hive query that return this results :
id,name,salary,accounts
1 ,John, 10000, {00920202, 00920203, 00920204}
2 ,Melissa, 5000, {00920205, 00920206}
Thanks in advance
Use collect_list if you are sure the account numbers are unique. Else use collect_set which eliminates duplicates.
select c.id,c.name,c.salary,collect_list(a.account_number) as all_accounts
from client c
join account a on a.client_id=c.id
group by c.id,c.name,c.salary

oracle left outer joins not showing null values but displays same value

Problem is in left outer join, when there are no rows in right side table then it does not display null values, it displays previous values....
Like this....
1 st Table contains
PGMTX_CODE PGMTX_MARKS PGMTX_TOTQSTN
-------------------------------------------
EE 1 5
EE 2 5
EE 3 0
EE 4 0
2 nd Table contains
PGMTX_CODE PGMTX_MARKS PGMTX_ACTUSEDQST
-------------------------------------------
EE 1 5
So I want result like...
PGMTX_MARKS PGMTX_TOTQSTN PGMTX_ACTUSEDQST
--------------------------------------------------
1 5 5
2 5 blank
3 0 blank
4 0 blank
I use query like this...
SELECT m.PGMTX_MARKS,
m.PGMTX_TOTQSTN,
tlm.PGMTX_ACTUSEDQST,
from PAPERGEN_MTL_OEX m
left OUTER JOIN PAPERGEN_TLMTL_OEX tlm
ON m.PGMTX_CODE=tlm.PGMTX_CODE
where m.PGMTX_CODE='EE'
order by m.PGMTX_MARKS
But I got result like
PGMTX_MARKS PGMTX_TOTQSTN PGMTX_ACTUSEDQST
--------------------------------------------------
1 5 5
2 5 5
3 0 5
4 0 5
Your join condition is wrong, should be
ON m.PGMTX_CODE=tlm.PGMTX_CODE AND m.PGMTX_MARKS = tlm.PGMTX_MARKS

Update query taking long time in oracle 10g

I have a table which holds more then 2 million records, I am trying to update a table using following query
UPDATE toc T
SET RANK =
65535
- (SELECT COUNT (*)
FROM toc T2
WHERE S_KEY LIKE '00010001%'
AND A_ID IS NOT NULL
AND T2.TARGET = T.TARGET
AND T2.RANK > T.RANK)
WHERE S_KEY LIKE '00010001%' AND A_ID IS NOT NULL
Usually this query tooks 5 mins to update 50000 rows in our staging db which is a exact replica of production db but in our production db it is taking 6 hours to execute...
I tried Oracle advisory to select the correct execution plan but nothing is working...
Plan
UPDATE STATEMENT ALL_ROWSCost: 329,471
6 UPDATE TT.TOC
2 TABLE ACCESS BY INDEX ROWID TABLE TT.TOC Cost: 5 Bytes: 4,173,236 Cardinality: 54,911
1 INDEX SKIP SCAN INDEX TT.DATASTAT_SORTKEY_IDX Cost: 4 Cardinality: 1
5 SORT AGGREGATE Bytes: 76 Cardinality: 1
4 TABLE ACCESS BY INDEX ROWID TABLE TT.TOC Cost: 5 Bytes: 76 Cardinality: 1
3 INDEX SKIP SCAN INDEX TT.DATASTAT_SORTKEY_IDX Cost: 4 Cardinality: 1
I can see the following wait events
1,066 db file sequential read 10,267 0 3,993 0 6 39,933,580
1,066 db file scattered read 413 0 188 0 6 1,876,464
Any help will be greatly appreciated.
here is the current list of indexes
DSTAT_SKEY_IDX D_STATUS 1
DSTAT_SKEY_IDX S_KEY 2
IDX$$_165A0002 N_LABEL 1
S_KEY_IDX S_KEY 1
XAK1_TOC N_RELATIONSHIP 1
XAK2_TOC TARGET 1
XAK2_TOC N_LABEL 2
XAK2_TOC D_STATUS 3
XAK2_TOC A_ID 4
XIE1_TOC N_RELBASE 1
XIF4_TOC SOURCE_FILE_ID 1
XIF5_TOC A_ID 1
XPK_TOC N_ID 1
Atif
You're doing a skip scan where you supposedly want to do a range scan.
A range scan is only possible when the index columns are ordered by descending selectivity - in your case it seems that it should be S_KEY - TARGET - RANK
Update: rewriting the query in different order wouldn't make any difference. What matters is the sequence of the columns in the indexes of that table.
first show us the current index columns for that table:
select index_name, column_name, column_position from all_ind_columns where table_name = 'TOC'
then you could create a new index, e.g.
create index toc_i_s_key_target_rank on toc (s_key, target, rank) compress;

Resources