Query to get list of Inventory Items for which there is no material transaction in Oracle - oracle

Have a small doubt I want to compile a SQL query in Inventory where I have to get those Items for which transactions have not been recorded during a period of at least a specified number of days.
The days could be 30 days or 2 months depends. So I want to get those items for which no transaction was recorded for lets say 30 days. Could anyone give me an idea of how to go about this thing?? I am using r12. I came up with the following query but it is giving many records. The commented portions of this query remains commented only
select distinct msi.segment1, msi.description, msi.primary_uom_code,
msi.inventory_item_id
from mtl_system_items_b msi /*,
mtl_material_transactions mmt*/
where /*msi.inventory_item_id = mmt.inventory_item_id
AND msi.organization_id = mmt.organization_id
AND NVL((SELECT SUM(transaction_quantity)
FROM mtl_onhand_quantities
WHERE inventory_item_id = msi.inventory_item_id),
0) = 0
AND TRUNC(mmt.transaction_date) <= SYSDATE - &D
AND*/
not exists
(select *
from mtl_material_transactions mmt
where msi.inventory_item_id = mmt.inventory_item_id
and msi.organization_id = mmt.organization_id
and trunc(mmt.transaction_date) < sysdate - &D)

Here is a variation of your query that will give all items with on hand inventory that have not been transacted in a determined number of days.
select distinct msi.segment1
,msi.description
,msi.primary_uom_code
--,msi.inventory_item_id
,q.organization_id
,q.quantity
from mtl_system_items_b msi
join (SELECT inventory_item_id, organization_id, SUM(transaction_quantity) quantity
FROM mtl_onhand_quantities
GROUP BY inventory_item_id, organization_id) q on msi.inventory_item_id = q.inventory_item_id and msi.organization_id=q.organization_id
where not exists (select *
from mtl_material_transactions mmt
where msi.inventory_item_id = mmt.inventory_item_id
and msi.organization_id = mmt.organization_id
and trunc(mmt.transaction_date) > sysdate - 180)
order by q.organization_id,msi.segment1;

Related

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...

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.

Oracle - What is the order of statement when using functions for filter in where clause

Refer Table WORKQUEUELOG with columns (ID,QueueTypeId,CreateDateTime,WorkId,InQ,OutQ)
There is an index available for (QueueTypeId,CreateDateTime,Id)
When trying to read the first X number of records with following query it is going for a full table search.
OPEN a_CursorHandle FOR
SELECT * FROM (
SELECT * FROM WORKQUEUELOG tbl
WHERE EX_CLS_WQLOG.FILTER(
tbl.QueueTypeId,
tbl.CreateDateTime,
NULL) = 1
AND EX_CLS_WQLOG.VALIDATION(
tbl.ID ,
tbl.WorkId ,
tbl.InQ ) = 1
ORDER BY tbl.QueueTypeId ASC,tbl.CreateDateTime ASC,tbl.Id ASC)
WHERE ROWNUM <= a_MaxCount;
We changed the query as following and started using the index for reading.
ie Validaiton function first and filter function as second.
OPEN a_CursorHandle FOR
SELECT * FROM (
SELECT * FROM WORKQUEUELOG tbl
WHERE EX_CLS_WQLOG.VALIDATION(
tbl.ID ,
tbl.WorkId,
tbl.InQ ) = 1
AND EX_CLS_WQLOG.FILTER(
tbl.QueueTypeId,
tbl.CreateDateTime,
NULL) = 1
ORDER BY tbl.QueueTypeId ASC,tbl.CreateDateTime ASC,tbl.Id ASC)
WHERE ROWNUM <= a_MaxCount;
What is the order of processing the SQL statement in oracle .? left to right or right to left.
From the above example this seems to be right to left . is this a consistent behavior. Is there any other efficient way to write this query.?

Oracle - Check if there is a data in range of date

I have three tables (receipts, receiptaddinfo, shops). I have select, that gives me a data with a all receipts from all shops since the declared date:
select *
from receipts r
join receipt receiptaddinfo ri on r.receiptid=ri.receiptid and r.shop=ri.shop
join shops s on ri.shop=s.shop and shoptype=0
where ri.creationtime >= '2016-05-19 00:00:00'
order by ri.creationtime desc
The table shops, contain all shops, however, I want to check if there is a shop, which had no 'sale/receipts' since the declared date. Could somebody help?
You can try the following SQL statement.
SELECT * from shops s
WHERE s.shoptype = 0
AND NOT EXISTS
(SELECT 1
FROM receipts r,
receiptaddinfo ri
WHERE r.receiptid = ri.receiptid
AND r.shop = ri.shop
AND ri.shop = s.shop
AND ri.creationtime >= '2016-05-19 00:00:00')

rownum and group by to limit to 1000 rows in detail

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'))

Resources