OracleAPPS- Can not get correct results for Suppliers - Bank query - sql

I am trying to fetch suppliers and bank details in Oracle apps. I am able to write a simple query where each supplier has a supplier site attached to it. Few of my sites doesn't have a record in table "iby_pmt_instr_uses_all". But even then I want to show them . So I am using the outer join on this table. But the issue is when I am putting this outer join condition, I am getting double the records in the query. I believe I am missing on some condition, but can not figure out which one.
SELECT *
FROM apps.iby_pmt_instr_uses_all instrument,
apps.iby_account_owners owners,
apps.iby_external_payees_all payees,
apps.iby_ext_bank_accounts ieb,
apps.ap_supplier_sites_all asa,
apps.ap_suppliers asp,
apps.ce_bank_branches_v cbbv
WHERE owners.ext_bank_account_id = ieb.ext_bank_account_id
AND owners.ext_bank_account_id = instrument.instrument_id(+)
AND payees.ext_payee_id = instrument.ext_pmt_party_id(+)
AND cbbv.branch_party_id = ieb.branch_id
AND payees.payee_party_id = owners.account_owner_party_id
AND payees.supplier_site_id = asa.vendor_site_id
AND asa.vendor_id = asp.vendor_id
AND asp.vendor_name = 'PANALYTICAL'
--and ieb.bank_account_num = asa.VENDOR_SITE_CODE
If I add and ieb.bank_account_num = asa.VENDOR_SITE_CODE this condition I get the correct record, but actually this is not the right join, because there is no relationship between these 2 columns, so this will fail for other suppliers.
Can you please suggest what additional join I can put , so that I get the right result.
Thanks

Related

SQL - join three tables based on (different) latest dates in two of them

Using Oracle SQL Developer, I have three tables with some common data that I need to join.
Appreciate any help on this!
Please refer to https://i.stack.imgur.com/f37Jh.png for the input and desired output (table formatting doesn't work on all tables).
These tables are made up in order to anonymize them, and in reality contain other data with millions of entries, but you could think of them as representing:
Product = Main product categories in a grocery store.
Subproduct = Subcategory products to the above. Each time the table is updated, the main product category may loses or get some new suproducts assigned to it. E.g. you can see that from May to June the Pulled pork entered while the Fishsoup was thrown out.
Issues = Status of the products, for example an apple is bad if it has brown spots on it..
What I need to find is: for each P_NAME, find the latest updated set of subproducts (SP_ID and SP_NAME), and append that information with the latest updated issue status (STATUS_FLAG).
Please note that each main product category gets its set of subproducts updated at individual occasions i.e. 1234 and 5678 might be "latest updated" on different dates.
I have tried multiple queries but failed each time. I am using combos of SELECT, LEFT OUTER JOIN, JOIN, MAX and GROUP BY.
Latest attempt, which gives me the combo of the first two tables, but missing the third:
SELECT
PRODUCT.P_NAME,
SUBPRODUCT.SP_PRODUCT_ID, SUBPRODUCT.SP_NAME, SUBPRODUCT.SP_ID, SUPPRODUCT.SP_VALUE_DATE
FROM SUBPRODUCT
LEFT OUTER JOIN PRODUCT ON PRODUCT.P_ID = SUBPRODUCT.SP_PRODUCT_ID
JOIN(SELECT SP_PRODUCT_ID, MAX(SP_VALUE_DATE) AS latestdate FROM SUBPRODUCT GROUP BY SP_PRODUCT_ID) sub ON
sub.SP_PRODUCT_ID = SUBPRODUCT.SP_PRODUCT_ID AND sub.latestDate = SUBPRODUCT.SP_VALUE_DATE;
Trying to find a row with a max value is a common SQL pattern - you can do it with a join, like your example, but it's usually more clear to use a subquery or a window function.
Correlated subquery example
select
PRODUCT.P_NAME,
SUBPRODUCT.SP_PRODUCT_ID, SUBPRODUCT.SP_NAME, SUBPRODUCT.SP_ID, SUPPRODUCT.SP_VALUE_DATE,
ISSUES.STATUS_FLAG, ISSUES.STATUS_LAST_UPDATED
from PRODUCT
join SUBPRODUCT
on PRODUCT.P_ID = SUBPRODUCT.SP_PRODUCT_ID
and SUBPRODUCT.SP_VALUE_DATE = (select max(S2.SP_VALUE_DATE) as latestDate
from SUBPRODUCT S2
where S2.SP_PRODUCT_ID = SUBPRODUCT.SP_PRODUCT_ID)
join ISSUES
on ISSUES.ISSUE_ID = SUBPRODUCT.SP_ID
and ISSUES.STATUS_LAST_UPDATED = (select max(I2.STATUS_LAST_UPDATED) as latestDate
from ISSUES I2
where I2.ISSUE_ID = ISSUES.ISSUE_ID)
Window function / inline view example
select
PRODUCT.P_NAME,
S.SP_PRODUCT_ID, S.SP_NAME, S.SP_ID, S.SP_VALUE_DATE,
I.STATUS_FLAG, I.STATUS_LAST_UPDATED
from PRODUCT
join (select SUBPRODUCT.*,
max(SP_VALUE_DATE) over (partition by SP_PRODUCT_ID) as latestDate
from SUBPRODUCT) S
on PRODUCT.P_ID = S.SP_PRODUCT_ID
and S.SP_VALUE_DATE = S.latestDate
join (select ISSUES.*,
max(STATUS_LAST_UPDATED) over (partition by ISSUE_ID) as latestDate
from ISSUES) I
on I.ISSUE_ID = S.SP_ID
and I.STATUS_LAST_UPDATED = I.latestDate
This often performs a bit better, but window functions can be tricky to understand.

How to show elements from 2 tables ( existing in one , another or both)

I have 2 tables than i need to fuse together for data analysis.
Table One ( shows year consumption of items with values, from a contract)
Table One fields : product code, quantity, total value, contract number
Table Two (shows contract defined included products)
Table Two fields : included product code, included quantity, total included value, contract number
I need to join both of them so that shows per contract, all the related products, both consumed or included, so that shows either i only have consumed but not included, included but not consumed and included and consumed...
Something like this :
Contract|Product Code|Consumed qty|Included Qty|Consumed Total|Included Total
CTC001|X0001|55|45|550|450
CTC001|X0002|20|NULL|200|NULL
CTC001|X0003|NULL|10|NULL|100
CTC002|X0001|10|10|100|100
Using inner join only shows the ones on both tables
Using left or right joins shows all from one table and similar and null's from other table...
My goal was to show from both tables, has the example
Any help or tip ?
(this is my current query, field names not all equal as example, but you get the idea :
SELECT dbo.USR_View_ArtIncludContr.strCodArtigo, dbo.USR_View_TotaisConsumos.strCodArtigo AS Expr2, dbo.USR_View_TotaisConsumos.QTDTOTAL,
dbo.USR_View_ArtIncludContr.fltQuantLimiteInc, dbo.USR_View_TotaisConsumos.VALORTOTAL, dbo.USR_View_ArtIncludContr.Total, dbo.USR_View_TotaisConsumos.strCodSecContrato,
dbo.USR_View_TotaisConsumos.strCodTpContrato, dbo.USR_View_TotaisConsumos.strCodExercContrato, dbo.USR_View_TotaisConsumos.intNumeroContrato, dbo.USR_View_ArtIncludContr.strCodSeccao,
dbo.USR_View_ArtIncludContr.strCodTpContrato AS Expr1, dbo.USR_View_ArtIncludContr.strCodExercicio, dbo.USR_View_ArtIncludContr.intNumero
FROM dbo.USR_View_ArtIncludContr INNER JOIN
dbo.USR_View_TotaisConsumos ON dbo.USR_View_ArtIncludContr.strCodSeccao = dbo.USR_View_TotaisConsumos.strCodSecContrato AND
dbo.USR_View_ArtIncludContr.strCodTpContrato = dbo.USR_View_TotaisConsumos.strCodTpContrato AND
dbo.USR_View_ArtIncludContr.strCodExercicio = dbo.USR_View_TotaisConsumos.strCodExercContrato AND dbo.USR_View_ArtIncludContr.intNumero = dbo.USR_View_TotaisConsumos.intNumeroContrato AND
dbo.USR_View_ArtIncludContr.strCodArtigo = dbo.USR_View_TotaisConsumos.strCodArtigo
Sounds like you want a full join:
SELECT aic.strCodArtigo, tc.strCodArtigo AS Expr2, tc.QTDTOTAL,
aic.fltQuantLimiteInc, tc.VALORTOTAL, aic.Total, tc.strCodSecContrato,
tc.strCodTpContrato, tc.strCodExercContrato, tc.intNumeroContrato, aic.strCodSeccao,
aic.strCodTpContrato AS Expr1, aic.strCodExercicio, aic.intNumero
FROM dbo.USR_View_ArtIncludContr aic FULL JOIN
dbo.USR_View_TotaisConsumos tc
ON aic.strCodSeccao = tc.strCodSecContrato AND
aic.strCodTpContrato = tc.strCodTpContrato AND
aic.strCodExercicio = tc.strCodExercContrato AND
aic.intNumero = tc.intNumeroContrato AND
aic.strCodArtigo = tc.strCodArtigo
Notice that column aliases make the query much easier to write and to read.
Just figure out an workaround...
i could use CASE WHEN for the contract and for product code...
Something like this in select :
"CASE WHEN AIC.strCodArtigo IS NULL THEN TC.strCodArtigo WHEN TC.strCodArtigo IS NULL THEN AIC.strCodArtigo ELSE AIC.strCodArtigo END AS ARTIGO "
And use FULL OUTER JOIN
In case anyone has a better way, i appreciate any opinion

SQL report filtering, results stop after first item

and thanks in advance. I am a newbie, working on one of my first reports. I have orders, which have a terminal assigned them (a "DC"). The report is set up to return all open orders, the "DC", and a few other columns (driver #, city, etc). I made a drop down filter to use so I can look at one, several, or all of the DCs. My problem is, it stops looking after the first item that is checked in the drop down list. So if the first item in the list has 100 orders, but the rest of them have thousands more, it only shows me the 100 orders. Am I making any sense here? I am not sure what information from my report's setup would be pertinent here.
This is the query that the report is based on. Using SQL Report Builder.
SELECT
o.OrderTrackingID,
cm.accountno,
o.ClientRefNo,
o.DCoName,
o.DStreet,
o.DCity,
o.DState,
o.DZip,
o.DZone,
t.TerminalName as 'OrderDC',
e.LastName as 'DrvLast',
e.FirstName as 'DrvFirst',
e.DriverNo,
et.TerminalName as 'DriverDC'
FROM Orders o
FULL JOIN OrderDrivers od ON o.OrderTrackingID = od.OrderTrackingID
FULL JOIN Employees e ON od.DriverID = e.ID
FULL JOIN ClientMaster cm ON o.ClientID = cm.ClientID
FULL JOIN Terminals t ON o.TerminalID = t.TerminalID
FULL JOIN Terminals et ON e.TerminalID = et.TerminalID
WHERE o.Status = 'N'
Order By o.aTimeStamp ASC
(I am writing this as an answer even if it isn't an complete answer mostly because the comment field is kind of limited.)
In the SQL you posted the below stands out as wrong
FULL JOIN Terminals t ON o.TerminalID = t.TerminalID
FULL JOIN Terminals et ON e.TerminalID = et.TerminalID
You are joining the same table twice but the is nothing that separated the two joins and this is my guess why you are not getting any more orders in your report.
I don't now what the drop down list corresponds to but I assume it is some kind of identifier in the Terminals table.
From a pure SQL point of view I would expect something like this
FULL JOIN Terminals t ON o.TerminalID = t.TerminalID
WHERE t.someColumn IN (value1, value2)
where value1 and value2 comes from the drop down list.
I see in your select part that you include the same column from both of the Terminals JOIN you have and I expect those two columns to always have the same values. You should need that column only once in your select list.
Not a solution but maybe this can get you in the right direction.

SQL LEFT JOIN WHERE not displaying right result

So I got this query:
Data structure:
Users
id---inlog----name----more stuff
llntoets
id---code----inlog----more stuff
oefeningen
id---speler---status----morestuff
(inlog and speler are always the same values for a user)
SELECT
// Some other stuff working
SUM(o.status) AS oefn
FROM users AS u
LEFT JOIN llntoets AS l
ON (u.inlog = l.inlog)
LEFT JOIN oefeningen AS o
ON (u.inlog = o.speler) AND o.status = 'afgewerkt'
WHERE
code = '$code'
GROUP BY l.inlog
ORDER BY klas ASC, klasnr ASC
Everything runs fine except 1 thing the oefn variable. It shows a number sometimes it shows the correct value and sometimes it shows a value that is much higher than it should be. Someone told me it could be because of the GROUP BY. Can someone help me pls?
It is supposed to count the total records from table oefeningen where status = 'afgewerkt' and where the speler is the inlog from users. Thanks, if you got other questions ask will try to explain more.
the SUM(o.status) in your query it is not supposed to count the total records of table oefeningen.
that sum is the sum of the values of all the joined rows that satisfy your criteria that can be a much higher number.
also note that applying the filter o.status = 'afgewerkt' you are performing a JOIN even if you wrote LEFT JOIN throghout the query.

Select DISTINCT values with 3 Inner joins

I have a few tables that I need to link together to get a specific value, here is my current query
SELECT DISTINCT bu.Email,iv.Code,ex.ExNumber
FROM Invoices AS iv
INNER JOIN Clients AS cs
ON iv.Code = cs.Code
INNER JOIN BusinessUser_ExNumbers AS ex
ON cs.ExNumber = ex.ExNumber
INNER JOIN BusinessUsers AS bu
ON ex.Userid = bu.Id
WHERE iv.BatchId = '74b43669-c80f-4b44-999c-a1dfe5695844' // Test value
Basically the links to my invoices are held in the invoice table, and what I need to do is send a link to the user who is specified as being the recipient of the invoice. The code works but it's not as 'distinct' as I would like. I dont want any rows with the same email and exnumber as any other row. Unfortunately if there is more than 1 iv.Code that ends up linking to a specific user I get multiple rows. I understand why this is but I can't think of a way to make that not happen.
Thanks!
EDIT: Sorry that was really stupid of me. I didn't need to select the iv.Code and that's what was causing the issue. That's probably why it didn't make much sense. Anyway since I posted the question I have tried Martin Smiths answer below and it works, so that is the answer to the question. If you don't need the iv.Code it can just be removed.
The below will return the MAX code in the event that there are multiple for a particular Email, Number combination.
SELECT bu.Email,
MAX(iv.Code) AS Code,
ex.ExNumber
FROM Invoices AS iv
INNER JOIN Clients AS cs
ON iv.Code = cs.Code
INNER JOIN BusinessUser_ExNumbers AS ex
ON cs.ExNumber = ex.ExNumber
INNER JOIN BusinessUsers AS bu
ON ex.Userid = bu.Id
WHERE iv.BatchId = '74b43669-c80f-4b44-999c-a1dfe5695844'
GROUP BY bu.Email,
ex.ExNumber