Exclude Debit Transactions - oracle

I have a need to select records from transactions table excluding certain transactions.
Bellow is a sample output of my tables.
TB_ACCOUNTS
CUSTCD ACCTNO PRDCD
100 10001 SATF
100 10002 SATF
200 10003 CUS
TB_TRANSACTIONS
TXNNO TXDATE ACCTNO CUSTOMER_NO TXAMT CASHFLOWTYPE
TX1 18-Jul-16 10001 100 5000 CR
TX2 18-Jul-16 10002 100 5000 DR
TX3 18-Jul-16 10003 200 3000 DR
TX4 18-Jul-16 10001 100 3000 CR
I want to select credit transactions where PRDCD is 'SATF' and exclude transfers between own accounts. For example customer 100 PRDCD is SATF and has two accounts. I want my select query to exclude credit transaction of amount 5000 because the debit account also belongs to the same customer. But include credit transaction of 3000 amount because the debit account is of different customer and type is not SATF.
So far I got bellow query but the output I'm getting is completely wrong.
select * from TB_TRANSACTIONS AB inner join TB_ACCOUNTS AC
on AB.ACCTNO=AC.ACCTNO
where AB.CASHFLOWTYPE='CR'
and AC.PRDCD='SATF'
and AB.TXNNO=
(select TXNNO from TB_TRANSACTIONS A, TB_ACCOUNTS B
where A.ACCTNO=B.ACCTNO
and A.TXAMT=AB.TXAMT
and A.CASHFLOWTYPE='DR'
and B.PRDCD=AC.PRDCD)
How to achieve the desired result?

You could use something like here:
select txnno, txdate, acctno, customer_no, txamt, cashflowtype, prdcd
from (
select t.*, a.prdcd,
count(distinct customer_no) over (partition by txdate, txamt) cnt
from tb_transactions t join tb_accounts a on t.acctno = a.acctno )
where cnt = 2 and cashflowtype = 'CR' and prdcd = 'SATF'
Here I assumed that txamt is unique for each date. I strongly suspect that this may be wrong assuption so be warned.
But there is nothing except this column that tells us that two rows belongs to the same operation.
In first query I used count() in analytic version. There are also possible other solutions, for instance (not) exists:
select *
from tb_transactions t join tb_accounts a on t.acctno = a.acctno
where
not exists (
select 1 from tb_transactions tt join tb_accounts ta on tt.acctno = ta.acctno
where tt.txdate = t.txdate and tt.txamt = t.txamt
and tt.cashflowtype = 'DR' and tt.customer_no = t.customer_no)
and cashflowtype = 'CR' and prdcd = 'SATF'
(sorry for any language mistakes)

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

Query to get list of Inventory Items for which there is no material transaction in 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;

Oracle Inner Table Query

I am trying to write a query in Oracle to give totals of active legal entities and inactive legal entities.
The query so far I have is:
select le.Name, b.LE_ID, count(*) As TOTAL, dead.LE_ID as DEAD
from BOOK b
left join Legal_Entity le on le.LE_ID = b.LE_ID
left join
(
select count(LE_ID) as LE_ID
from BOOK
where (Name like '%DUMMY%' or name like '%TEST%' or name like '%DEAD%' or name like '%DO NOT%' or status <> 'Active')
) dead on dead.LE_ID = b.LE_ID
where b.LE_ID = 1234
group by le.Name, b.LE_ID, dead.LE_ID
order by b.LE_ID;
The results I am expecting are:
Name EntityID Total Dead
Entity A 1234 500 200
i.e. for Book.LE_ID = 1234 I would like one row in the result set and a column with the Total number i.e. select * from Book where LE_ID = 1234 and a column with the number of dead books i.e. the inner query
But at the moment, my query is returning NULL for the number of dead rows.
The inner query is working without issue, but I'm clearly missing something here.
I am not sure, but shouldn't it be something like this?
select le.Name, b.LE_ID, count(*) As TOTAL, dead.DEAD as DEAD
from BOOK b
left join Legal_Entity le on le.LE_ID = b.LE_ID
left join
(
select LE_ID, count(LE_ID) as DEAD
from BOOK
where (Name like '%DUMMY%' or name like '%TEST%' or name like '%DEAD%' or name like '%DO NOT%' or status <> 'Active')
group by LE_ID
) dead on dead.LE_ID = b.LE_ID
where b.LE_ID = 1234
group by le.Name, b.LE_ID, dead.LE_ID
order by b.LE_ID;
It is a bit hard to figure out exactly what you are trying to do. After all, you are trying to join between a count and an id, something that is not likely to lead to success.
Your example has a name 'Entity A'. By the rules specified in the query for "dead" entities, there should be none. The name doesn't match this rule.
In all likelihood, you want conditional aggregation. Here is a query that I think gets the totals over all entities:
select count(*) As TOTAL,
sum(case when Name like '%DUMMY%' or name like '%TEST%' or name like '%DEAD%' or name like '%DO NOT%' or status <> 'Active'
then 1 else 0
end) as dead
from BOOK b left join
Legal_Entity le
on le.LE_ID = b.LE_ID;

Oracle Join Two Queries With Distinct Answer

I need help in linking two tables together to bring back data as I need.
I have two queries:
The first is as follows:
SELECT
POI.PO_ID as PO_ID, SUM(POI.INV_QTY) AS INV_QTY, POI.INV_NUMBER,
PO.SUP_SUP_ID AS SUPPLIER
FROM TABLE1 POI, PUR_ORDS PO
WHERE POI.PO_ID = '56886' AND POI.PO_ID = PO.PO_ID
GROUP BY POI.PO_ID, POI.INV_NUMBER, PO.SUP_SUP_ID
ORDER BY POI.INV_NUMBER ASC
The Results of this query are as follows:
PO_ID|INV_QTY|INV_NUMBER|SUPPLIER
---------------------------------
56886| 105|INV1 |SUP1
56886| 106|INV2 |SUP1
The second query I have is this:
SELECT
DIL.PO_PO_ID, sum(DIL.ACPTD_QTY) as ACPTD_QTY,
DIL.DLVD_DLVY_NUMB AS DEL_NUM
FROM TABLE2 DIL
where DIL.PO_PO_ID = '56886'
GROUP BY PO_PO_ID, DIL.DLVD_DLVY_NUMB
order by del_num
The Results of this query are as follows:
PO_PO_ID|ACPTD_QTY|DEL_NUM
--------------------------
56886| 105| 1
56886| 106| 2
Now I am attempting to join the two tables, but I get multiple values appearing, using the following:
SELECT DISTINCT(PO_ID), INV_NUMBER, INV_QTY, SUPPLIER, ACPTD_QTY, DEL_NUM
FROM
(SELECT
SELECT POI.PO_ID as PO_ID, SUM(POI.INV_QTY) AS INV_QTY,
POI.INV_NUMBER, PO.SUP_SUP_ID AS SUPPLIER
FROM TABLE1 POI, PUR_ORDS PO
WHERE POI.PO_ID = '56886'
AND POI.PO_ID = PO.PO_ID
GROUP BY POI.PO_ID, POI.INV_NUMBER, PO.SUP_SUP_ID
ORDER BY POI.INV_NUMBER ASC) POINET
INNER JOIN
(SELECT DIL.PO_PO_ID, sum(DIL.ACPTD_QTY) as ACPTD_QTY,
DIL.DLVD_DLVY_NUMB AS DEL_NUM
FROM TABLE 2 DIL
where DIL.PO_PO_ID = '56886'
GROUP BY PO_PO_ID, DIL.DLVD_DLVY_NUMB
order by DEL_NUM) DILV
ON DILV.PO_PO_ID = POINET.PO_ID
GROUP BY PO_ID, INV_NUMBER, INV_QTY, SUPPLIER, ACPTD_QTY, DEL_NUM
ORDER BY INV_NUMBER
However the dataset I get is this:
PO_ID|INV_NUMBER |INV_QTY|SUPPLIER|ACPTD_QTY|DEL_NUM
-----------------------------------------------------
56886|K-101/2014-15| 105|SUP1 | 105| 1
56886|K-101/2014-15| 105|SUP1 | 106| 2
56886|K-107/2014-15| 106|SUP1 | 105| 1
56886|K-107/2014-15| 106|SUP1 | 106| 2
However I need it show the following:
PO_ID|INV_NUMBER |INV_QTY|SUPPLIER|ACPTD_QTY|DEL_NUM
------------------------------------------------------
56886|K-101/2014-15| 105|SUP1 | 105| 1
56886|K-107/2014-15| 106|SUP1 | 106| 2
What do I need to do, to tweak my query?
Any help would be much appreciated.
I think you just need to modify your join statement to join on both columns
ON DILV.PO_PO_ID = POINET.PO_ID
AND DILV.INV_QTY = POINET.ACPTD_QTY
Actually, you can probably leave out the PO_ID, because I it's the same in both subqueries:
i.e. Just do this (on the third last line):
ON DILV.INV_QTY = POINET.ACPTD_QTY

Tsql: what is the best way to retrieve some records with a specific criteria?

I have a table (Cars) which saves some characteristics car like EngineNo, LastProductionStepId, NodyNo, ...
Besides, I have another table (CarSteps) which saves all steps that a specific car should pass during its manufacturing proccess like Engine Assigning(Id = 2), Engraving(3), PrePaint(4), Paint(5), AfterPaint(6), Confirmation(7), Delivery(8)
I would like to get all cars that are between PrePaint and Confirmation at the moment:
select cr.Id, cr.BodyNo, cr.LastStepId
from Cars cr WITH (NOLOCK)
inner join CarSteps steps WITH (NOLOCK) on cr.Id = trace.CarId and cr.LastStepId=trace.StepId
where
cr.LastStepId >= 4
AND cr.[Status] = 1
AND steps.[Status] = 1
AND not exists ( select *
from CarSteps steps1 WITH (NOLOCK)
where steps1.CarId = cr.Id
AND steps1.StepId >= 7 AND steps1.Status = 1
)
Because CarSteps has many records (44 million) the query is slow .
what is your opinion? is there any better way to get those cars?
Looking at your query I see a join from Cars to CarSteps, I see you joining to trace.CarId and trace.StepId is. trace is not defined in your query.
from
Cars cr WITH (NOLOCK) inner join
CarSteps steps WITH (NOLOCK) on
cr.Id = trace.CarId and
cr.LastStepId=trace.StepId
I may be able to help if i have better understand the fully query.
What does the execution plan reveal?

Resources