rownum and group by to limit to 1000 rows in detail - oracle

I need to limit to 1000 rows in detail table EL8_STGG_CEHL_EXCP for each unique combination keys(AST_ID,PRCS_ID,PRCS_NME,PRCS_STEP_NME,SRC_APPL_LOG_DT) in the EL8_STGG_CEHL_LOG.
For example - If there are 3 unique combination keys, I expect 3000 rows in the detail table.
SELECT
E.AST_ID,
E.PRCS_ID,
E.PRCS_NME,
E.PRCS_STEP_NME,
E.SRC_APPL_LOG_DT
FROM EL8_STGG_CEHL_EXCP E,EL8_STGG_CEHL_LOG L
WHERE
L.AST_ID = E.AST_ID
AND L.PRCS_ID = E.PRCS_ID
AND L.PRCS_NME = E.PRCS_NME
AND L.PRCS_STEP_NME = E.PRCS_STEP_NME
AND L.SRC_APPL_LOG_DT = E.SRC_APPL_LOG_DT
AND (L.CEHL_PICK_UP_IND IS NULL OR UPPER(L.CEHL_PICK_UP_IND) not in ('Y','P'))
GROUP BY
E.AST_ID,
E.PRCS_ID,
E.PRCS_NME,
E.PRCS_STEP_NME,
E.SRC_APPL_LOG_DT
it would be great help if anyone can help me out
Thanks

Untested... that's a lot of data to mock up.
Basically, I use my favorite analytic function, row_number()
with limited as (
select
L.*,
row_number() over (partition by AST_ID,PRCS_ID,PRCS_NME,
PRCS_STEP_NME,SRC_APPL_LOG_DT order by rownum) as rn
from EL8_STGG_CEHL_LOG L
)
SELECT
E.AST_ID,
E.PRCS_ID,
E.PRCS_NME,
E.PRCS_STEP_NME,
E.SRC_APPL_LOG_DT
FROM
EL8_STGG_CEHL_EXCP E,
limited L
WHERE
L.AST_ID = E.AST_ID
AND L.PRCS_ID = E.PRCS_ID
AND L.PRCS_NME = E.PRCS_NME
AND L.PRCS_STEP_NME = E.PRCS_STEP_NME
AND L.SRC_APPL_LOG_DT = E.SRC_APPL_LOG_DT
AND L.RN <= 1000
AND (L.CEHL_PICK_UP_IND IS NULL OR UPPER(L.CEHL_PICK_UP_IND) not in ('Y','P'))

Related

CTX index in oracle is quite slow?

I am using CTX index in oracle column .
I have two table
xyz have 6 million record.
abc has 100k record
What i want to achieve is this.
Scenario - I have to union them and then i need the data in order by of date . And then i need pagination record on them.
select page_loc, blurb_id, article_id, hit_date,val_rank from (
SELECT REGEXP_REPLACE(regexp_replace(page_loc, '^.*mercer\.com'),'\?.*$') AS page_loc,
blurb_id, article_id, hit_date,RANK() OVER (ORDER BY hit_date DESC) AS val_rank
from (
SELECT page_loc, blurb_id, article_id, hit_date
FROM abc u INNER JOIN person p ON u.person_id=p.person_id
WHERE (CONTAINS(u.page_loc,v_pattern) > 0 )
UNION ALL
SELECT e page_loc, blurb_id, article_id, hit_date
FROM xyz u INNER JOIN person p ON u.person_id=p.person_id
WHERE ( CONTAINS(u.page_loc,v_pattern) > 0)
) p
left join
company c on c.company_id = p.company_id
) a
where val_rank between (v_page_no -1) * 10 and v_page_no * 10
v_pattern --> searching text
v_page_no --> page count
It take long time when i have record for some v_pattern more e.g 100k,
for example a word have 2 million record. it take more than 20 min.
Any idea what can i do . or it is not possible with oracle.
NOTE :- when i analysis it i found order by and pagination making it slow . How can i overcome that

How to Delete these Records in Netezza(Aginity)

I Written a Query to Identify the Duplicate records.
As Below.
WITH DUPS AS
(SELECT A_SURVEYID,
CAST(e_responsedate AS DATE) AS e_responsedate,
E_LG_VM_SURVEY_TYPE_ENUM
FROM TRANSIENT..INTERIM_NPS_SURVEY_MOBILE_RESULTS_20170909 a
GROUP BY A_SURVEYID,
CAST(e_responsedate AS DATE),
E_LG_VM_SURVEY_TYPE_ENUM
HAVING COUNT(*) > 1
),
RANKED AS
(SELECT R.DRS_RECORD_ID,
R.A_SURVEYID,
R.e_responsedate ,
ROW_NUMBER() OVER ( PARTITION BY R.A_SURVEYID, CAST(R.e_responsedate AS DATE),
R.E_LG_VM_SURVEY_TYPE_ENUM ORDER BY SUBSTR(R.DRS_RECORD_ID, INSTR(':', R.DRS_RECORD_ID, 37) + 1, 14) DESC,
SUBSTR(R.DRS_RECORD_ID, INSTR(':', R.DRS_RECORD_ID, 32) + 1, 4) ASC ) AS DR
FROM TRANSIENT..INTERIM_NPS_SURVEY_MOBILE_RESULTS_20170909 R
INNER JOIN DUPS
ON R.A_SURVEYID = DUPS.A_SURVEYID
AND CAST(R.e_responsedate AS DATE) = DUPS.e_responsedate
AND R.E_LG_VM_SURVEY_TYPE_ENUM = DUPS.E_LG_VM_SURVEY_TYPE_ENUM
)
SELECT *
FROM TRANSIENT..INTERIM_NPS_SURVEY_MOBILE_RESULTS_20170909 F
INNER JOIN RANKED
ON F.DRS_RECORD_ID = RANKED.DRS_RECORD_ID
WHERE RANKED.DR > 1
--
By Using the Above Query am able to retrieve the records.(some 6000+ ).
But am unable to delete those records.
Can you please help me on this.
Regards,
Krish
You are very close. In the last 5 lines, do this instead:
Delete from FROM TRANSIENT..INTERIM_NPS_SURVEY_MOBILE_RESULTS_2017090
Where DRS_RECORD_ID in (
Select DRS_RECORD_ID from RANKED WHERE DR>1)
Should work :)
BTW: I'm pretty sure this can be done with less code, but that is not important...

Return duplicate min values

See the table below for reference. I need to return duplicate rows containing the min value.
In this example I want to show only the 2 rows that have SLAT_LEN = 30 or rather the min SLAT_LEN. I tried rank but when I do it does a consecutive rank. I want the duplicate sizes to have the same rank and to rank consecutively by size.
The sizes change so I can't just use a condition like SLAT_LEN = 30.
Or is there a different approach that I should take?
select *
from(
select lg.wd_demand_id,wm.slat_len, wm.prof_size, wm.wd_material_id, wm.color, rank() over ( partition by wm.slat_len order by lg.wd_demand_id) as rank
from wd_demand_log lg, wd_bins wb, wd_material wm, wd_bins_material wbm
where lg.wd_bins_id = wb.wd_bins_id
and lg.wd_material_id = wm.wd_material_id
and lg.wd_bins_id = wbm.wd_bins_id
and lg.wd_material_id = wbm.wd_material_id
AND lg.plant_id = 44 AND lg.dept_id = 220 AND wb.plant_id = 44 AND wb.dept_id = 220
AND NOT EXISTS(SELECT dmpln.wd_demand_id FROM wd_demnd_pln_inv dmpln WHERE dmpln.wd_demand_id = lg.wd_demand_id)
AND wm.prof_size = '2' AND wm.color = 450
AND lg.wd_po_error is null)
You'd use PARTITION BY to give the range in which to rank. The ORDER BY specifies the ranking. So in your case you'll need something like
rank() over (order by wm.slat_len)
In case you have Oracle 12c you can limit your results with FETCH FIRST:
ORDER BY wm.slat_len
FETCH FIRST 1 ROW WITH TIES;
Perhaps I am not understanding the problem correctly, but here is my potential solution:
WITH aset
AS (SELECT lg.wd_demand_id
, wm.slat_len
, wm.prof_size
, wm.wd_material_id
, wm.color
FROM wd_demand_log lg, wd_bins wb, wd_material wm
, wd_bins_material wbm
WHERE lg.wd_bins_id = wb.wd_bins_id
AND lg.wd_material_id = wm.wd_material_id
AND lg.wd_bins_id = wbm.wd_bins_id
AND lg.wd_material_id = wbm.wd_material_id
AND lg.plant_id = 44
AND lg.dept_id = 220
AND wb.plant_id = 44
AND wb.dept_id = 220
AND NOT EXISTS
(SELECT dmpln.wd_demand_id
FROM wd_demnd_pln_inv dmpln
WHERE dmpln.wd_demand_id = lg.wd_demand_id)
AND wm.prof_size = '2'
AND wm.color = 450
AND lg.wd_po_error IS NULL)
SELECT *
FROM aset
WHERE slat_len = (SELECT MIN (slat_len)
FROM aset)

Oracle 11g Count query slowness

I have written one query which provides me a count of item type using group by.
The select query if I fire without group up and count provides results in less than a second on sql developer.
However count query runs for ever that I have to kill the process.
Below is the query ..
WITH permList
AS (SELECT user_perm_level,
item_category,
active
FROM usr_perm_levels
WHERE usr_pk = '7'
UNION ALL
SELECT home_key,
'ALL',
0
FROM user_home_list
WHERE usr_pk = 7
UNION ALL
SELECT home_key,
'UYT',
0
FROM user_home_list
WHERE usr_pk = 7
UNION ALL
SELECT home_key,
'ABR',
0
FROM user_home_list
WHERE usr_pk = 7),
list1
AS (SELECT a.parent_home_key,
b.item_category
FROM user_hier a
INNER JOIN indhome b
ON a.child_home_key = b.user_perm_level),
list2
AS ((SELECT oh.child_home_key,
u.item_category
FROM indhome U
INNER JOIN user_hier oh
ON u.user_perm_level = oh.parent_home_key
AND u.active = 1)
UNION ALL
SELECT user_perm_level,
item_category
FROM indhome)
SELECT type,
Count(*)
FROM inventory
WHERE is_available = 0
AND active = 1
AND EXISTS (SELECT 0
FROM inventory_auth c
WHERE EXISTS (SELECT 0
FROM orglist1
WHERE c.user_perm_level = orglist1.parent_home_key
AND c.item_category =
orglist1.item_category
AND c.active = 1)
OR EXISTS (SELECT 0
FROM orglist2
WHERE c.user_perm_level = orglist2.child_home_key
AND c.item_category =
orglist2.item_category)
AND inventory.item_key = c.item_key
AND inventory.item_category = c.item_category)
GROUP BY type;
In explain plan I see that Cost of group by clause is 145297221173.
Now here inventory table has 10 million records and the exists block which works around inventory table also runs into 15 million records.
Where as views permList, list1 and list2 have records only in 100s.
I have tried various combination but none of them seems to bring better performance. Such as I have tried inner join between inventory and inner query with exists clause but that doesn't help much.

Display only the largest count in a group by statment

I'm trying to display only the largest group in this group by statement;
SELECT COUNT(type) AS booking, type FROM booking b, room r WHERE r.rno = b.rno AND r.hno = b.hno GROUP BY type;
I modified it so we get this query response now you can see group double is larger then family.
BOOKING TYPE
5 double
2 family
I know there is a HAVING keyword you can add in order display only a count compared to a number so I could do COUNT(type) HAVING > 2 or similar but that's not very dynamic and that would only work in this instance because I know the two amounts.
ORDER BY COUNT(type) DESC LIMIT 1
There isn't a having statement that does this. But you can use rownum with a subquery:
select t.*
from (SELECT COUNT(type) AS booking, type
FROM booking b join
room r
on r.rno = b.rno AND r.hno = b.hno
GROUP BY type
order by count(type) desc
) t
where rownum = 1;
Just order your query..
order by booking desc
regards
TRY this
SELECT COUNT(type) AS booking, type FROM booking b, room r WHERE r.rno = b.rno AND r.hno = b.hno ORDER BY type DESC LIMIT 1

Resources