Multiple Join on the same table-Oracle - sql

I tried the below query
SELECT Customer.*,
ElectrnicItem.Product1 AS ElectronicItem1,
ElectrnicItem.Product2 AS ElectronicItem2,
ElectrnicItem.Product3 AS ElectronicItem3,
ApparelItem.Product1 AS ApparelItem1,
ApparelItem.Product2 AS ApparelItem2,
ApparelItem.Product3 AS ApparelItem3
FROM Customer
LEFT JOIN Inventory AS ElectrnicItem
ON (Customer.CustomerID = ElectrnicItem.CustomerID)
LEFT JOIN Inventory AS ApparelItem
ON (Customer.CustomerID = ApparelItem.CustomerID)
but it always returns:
ORA-00918 column ambiguously defined

You're missing any predicate to identify rows in Inventory as either 'Electronic' or 'Apparel' for one thing. Not sure that's the fix though.

How about this?
SELECT a.customer_id, a.customer_name, b.product1 electronicitem1,
b.product2 electronicitem2, b.product3 electronicitem3,
c.product1 apparelitem1, c.product2 apparelitem2,
c.product3 apparelitem3
FROM customer a, inventory b, inventory c
WHERE a.customer_id = b.customer_id(+)
AND b.product_type(+) = 'Electronic'
AND a.customer_id = c.customer_id(+)
AND c.product_type(+) = 'Apparel';

I created tables Customer and Inventory, also inserted the values that you have provided. The following is the query :
select customer.*,ElectrnicItem.Product1 as ElectronicItem1,
ElectrnicItem.Product2 as ElectronicItem2,
ElectrnicItem.Product3 as ElectronicItem3,
ApparelItem.Product1 as ApparelItem1,
ApparelItem.Product2 as ApparelItem2,
ApparelItem.Product3 as ApparelItem3
from customer
left join inventory as ElectrnicItem on
(customer.CustomerID = ElectrnicItem.CustomerID )
left join inventory as ApparelItem
on (customer.CustomerID = ApparelItem.CustomerID )
It works fine and gives the following result:
1 David Miller mobile headphone trimmer mobile headphone trimmer
2 Johnson jeans tshirt NULL jeans tshirt NULL
3 Diggs NULL NULL NULL NULL NULL NULL
The expected output that you have mentioned will never be achieved. Because Customer table contains CustomerId and CustomerName, Customer.* will retrieve both CustomerId and CustomerName. So CustomerName column can not contain any NULL
values.

Ok, a bit late, but...
You donĀ“t use AS to alias a table in Oracle, only to alias a column. Try to drop all those AS from the tables aliases:
SELECT Customer.*,
ElectrnicItem.Product1 AS ElectronicItem1,
ElectrnicItem.Product2 AS ElectronicItem2,
ElectrnicItem.Product3 AS ElectronicItem3,
ApparelItem.Product1 AS ApparelItem1,
ApparelItem.Product2 AS ApparelItem2,
ApparelItem.Product3 AS ApparelItem3
FROM Customer
LEFT JOIN Inventory ElectrnicItem
ON (Customer.CustomerID = ElectrnicItem.CustomerID)
LEFT JOIN Inventory ApparelItem
ON (Customer.CustomerID = ApparelItem.CustomerID)

Related

Selecting table to use in FROM clause based on certain condition

I have the following schema :
Purchase : pur_dt | pur_amt | item_code | quantity
ItemListForSoftware : item_code | item_desc | ...
ItemListForHardware : item_code | item_desc | ...
Now, I need to fetch item_desc from either of the Item tables based on the item_code of Purchase.
If item_code starts with S then it should look up in ItemListForSoftware
else from ItemListForHardware
Something like this
if(item_code starts with S){
select pur_dt,pur_amt,item_desc,quantity from Purchase, ItemListForSoftware where Purchase.item_code=ItemListForSoftware.item_code
}else{
select pur_dt,pur_amt,item_desc,quantity from Purchase, ItemListForHardware where Purchase.item_code=ItemListForHardware.item_code
}
Is there a way to do this via single SQL Query?
Is this what you want?
select p.pur_dt, p.pur_amt,
coalesce(ifs.item_desc, ifh.item_desc) as item_desc,
p.quantity
from Purchase p left join
ItemListForSoftware ifs
on p.item_code = ifs.item_code and
p.item_code like 'S%' left join
ItemListForHardware ifh
on p.item_code = ifh.item_code and
p.item_code not like 'S%';
Note the correct JOIN syntax.
You can solve this problem by LEFT JOINing to both tables and using the item_code to select the appropriate data:
SELECT p.pur_dt, p.pur_amt,
CASE WHEN LEFT(p.item_code, 1) = 'S' THEN s.item_desc
ELSE h.item_desc
END AS item_desc
p.quantity
FROM Purchase p
LEFT JOIN ItemListForSoftware s ON p.item_code=s.item_code
LEFT JOIN ItemListForHardware h ON p.item_code=h.item_code
Actually it is just as simple as you wrote:
select
pur_dt,
pur_amt,
case
when left(item_cide, 1) = 'S' then
(select item_desc from ItemListForSoftware as d where d.item_code = p.item_code)
else
(select item_desc from ItemListForHardware as d where d.item_code = p.item_code)
end as item_desc,
quantity
from Purchase as p;
Surely it will to work only if there is only 0 or 1 row in ItemListForSoftware and ItemListForHardware tables per item.
PS: Note that it could be faster a bit then joining three tables.

Sql Joining 3 Tables Query for Loan Total Result

I have to get the total of Customer Loan from 3 tables the two tables are given loan to sum and the other subtract the paid amount and the tables have Customer ID in common. so far I can get the result only if the Customer ID exist in all tables but if it doesn't exist in one table I won't get Customer in my result. or I get NULL customer IDs when I anchor to the customer.
SELECT
AS1.C_ID AS [Customer ID],
ISNULL(AS1.OldCustomerLoan, 0) AS [Old Loan],
ISNULL(AS2.NewGivenLoan, 0) AS [New Given Loan],
ISNULL(AS3.LoanPaid, 0) AS [PaidLoanAmount],
(ISNULL(AS1.OldCustomerLoan, 0) +
ISNULL(AS2.NewGivenLoan, 0) -
ISNULL(AS3.LoanPaid,0) ) AS Total
FROM
Customer C
LEFT OUTER JOIN
(SELECT
MOC.C_ID,
SUM(MOC.Quantity) AS OldCustomerLoan
FROM
Money_On_Customer MOC (NOLOCK)
GROUP BY
MOC.C_ID) AS1
ON c.C_Id = AS1.C_Id
LEFT OUTER JOIN
(SELECT
NGL.C_ID
,SUM(NGL.G_Take_Loan) AS NewGivenLoan
FROM
Given_Loan NGL
GROUP BY
NGL.C_ID) AS2
ON c.C_Id = AS2.C_Id
LEFT OUTER JOIN
(SELECT
GLP.C_ID, SUM(GLP.G_P_Loan) AS LoanPaid
FROM
Given_Loan_Paid GLP
GROUP BY
GLP.C_ID ) AS3
ON c.C_Id = AS3.C_Id
Here Is a picture of my two results:
When I get NULL Customer IDs
When I don't get All the Customers
You need to use c.c_id for the first column
In order to only get records where they exist in at least one of the tables you can add this to you query, just put you current query in place of the dots, and add the leftid col
Select *
From
(Select c.c_id custonerid,
Coalesce(Coalesce(as1.c_id,as2.c_id),as3.c_id) leftid,......
From ....
) ilv
Where leftid is not null
You might be able to just add
Where coalesce(coalesce(as1.c_id,as2.c_id),as3.c_id) is not null
To then end of your query
#Ab Bennett's answer is right,
because you should use your main(master) table's primary key column
if Customer ID is not available in as1 (Money_On_Customer) it will show null.
Hope you understand my explanation.
UPDATE:
and use following for getting customer id
COALESCE(c.C_Id, AS1.C_Id, AS2.C_Id)
you will get first not null Customer ID
Here is My answer with the help of #Ab Bennett
Select *
From
(
SELECT
C.C_Name AS [Customer ID],
ISNULL(AS1.OldCustomerLoan, 0) AS [Old Loan],
ISNULL(AS2.NewGivenLoan, 0) AS [New Given Loan],
ISNULL(AS3.LoanPaid, 0) AS [PaidLoanAmount],
(ISNULL(AS1.OldCustomerLoan, 0) +
ISNULL(AS2.NewGivenLoan, 0) -
ISNULL(AS3.LoanPaid,0) ) AS Total
FROM
Customer C
LEFT OUTER JOIN
(SELECT
MOC.C_ID,
SUM(MOC.Quantity) AS OldCustomerLoan
FROM
Money_On_Customer MOC (NOLOCK)
GROUP BY
MOC.C_ID) AS1
ON c.C_Id = AS1.C_Id
LEFT OUTER JOIN
(SELECT
NGL.C_ID
,SUM(NGL.G_Take_Loan) AS NewGivenLoan
FROM
Given_Loan NGL
GROUP BY
NGL.C_ID) AS2
ON c.C_Id = AS2.C_Id
LEFT OUTER JOIN
(SELECT
GLP.C_ID, SUM(GLP.G_P_Loan) AS LoanPaid
FROM
Given_Loan_Paid GLP
GROUP BY
GLP.C_ID ) AS3
ON c.C_Id = AS3.C_Id) ilv
Where not ([Old Loan] = 0 and [New Given Loan]=0 and PaidLoanAmount =0 )

SQL Using Multiply 3 Times with different ID's

I have tables called Products and ProductsDetails. I want to get something like the price of an order. So let's say I want 5 pairs of "Headphonesv1" ( Comparing with not ID but name, since name could change ), 2 packs of "GumOrbit" and 7 packs of "crisps". Pair of headphonesv1 costs 10$, gum 1$ and crisps 2$. So the answer that I should get is bill ID, Bill date, and TotalCost which is = 66. My question is how do I make multiple calculations? The code that I've been trying with one at least but I get syntax error:
SELECT Products.billID, Products.Date, (ProductsDetails.Price * 5 WHERE ProductsDetails.name LIKE 'Headphonesv1')
FROM Products INNER JOIN ProductsDetails ON Products.billdID = ProductsDetails.billID
Also have tried inserting SELECT inside () but then the values that I get are wrong and creating one more inner join inside doesn't seem promising
I think if you just want to see that total cost for multiple items you can use a aggregate and case expression to get the SUM.
SELECT Products.billID,
Products.Date,
SUM(CASE WHEN ProductsDetails.name LIKE 'Headphonesv1' THEN ProductsDetails.Price * 5
WHEN ProductsDetails.name LIKE 'GumOrbit' THEN ProductsDetails.Price * 2
WHEN ProductsDetails.name LIKE 'crisps' THEN ProductsDetails.Price * 7
END) TotalCost
FROM Products
INNER JOIN ProductsDetails ON Products.billdID = ProductsDetails.billID
GROUP BY Products.billID,
Products.Date
this seems very hard coded to serve much use though
Your previous code has a few synax erros. you are closing your parenthesis in the wrong location, and the FROM ... clause should be before the WHERE ... clause. Change your code to this:
SELECT Products.billID, Products.Date, (ProductsDetails.Price * 5)
FROM Products INNER JOIN ProductsDetails ON Products.billdID = ProductsDetails.billID
WHERE ProductsDetails.name LIKE 'Headphonesv1'
and let me know if it works now.
Edited:
The OP requested how to obtain that information for more than one Product. In that case you could switch the statement to:
SELECT SUM(Cost)
FROM (
SELECT Products.billID, Products.Date,
(ProductsDetails.Price *
(CASE WHEN ProductsDetails.name='Headphonesv1' THEN 5 ELSE
CASE WHEN ProductsDetails.name='GumOrbit' THEN 7 ELSE 0 END
END)
) AS Cost
FROM Products INNER JOIN ProductsDetails ON Products.billdID = ProductsDetails.billID
WHERE (ProductsDetails.name = 'Headphonesv1') OR (ProductsDetails.name = 'GumOrbit')
)
And you can continue to add more products.
You probably have another two tables: cart(cartID int/*,more info*/) and cartItems(cartID int /*FK*/, item varchar(50),qty int) where you add something. Finally,
select sum(pd.price * ci.qty) tot
FROM Products p
INNER JOIN ProductsDetails pd ON p.billdID = pd.billID
inner join cartItems ci on ci.item = pd.name
inner join cart c on c.cartID = ci.cartID
where c.cartID = 123456

how to join two tables where second table has condtion

I have two tables like
shopping_cart_table and customer_table
shopping_cart_table has fields shoppingcart_id | home_No|
customer_table has fields shoppingcart_id | status| customer_type|
I want to get the home_No from shopping_cart_table WHERE (customer_table.status is null OR customer_table.status='Y') AND customer_table.customer_type='X'
both table can join from shoppingcart_id
Actually this is just basic.
You can use join & put where conditions.
Select a.home_No
from shopping_cart_table as a
inner join customer_table as b
on a.shoppingcart_id = b.shoppingcart_id
where nvl(b.status,'Y') = 'Y'
and customer_type='X'
select home_No
from shopping_cart_table, customer_table
WHERE shopping_cart_table.shoppingcart_id = customer_table.shoppingcart_id
AND(customer_table.status is not null OR customer_table.status='Y') AND
customer_table.customer_type='X'
But this condition looks a bit strange:
(customer_table.status is not null OR customer_table.status='Y')
Maybe you'd want to change it for
nvl(customer_table.status,'Y')='Y'
aqssuming that 'not' was put there by a mistake
You can try this query:
SELECT sct.home_no
FROM shopping_cart_table AS sct
, customer_table AS ct
WHERE sct.shoppingcart_id = ct.shoppingcart_id
AND (
ct.status IS NOT NULL
OR ct.status = 'Y')
AND ct.customer_type = 'X'

Find out for missing items across 2 tables

Basically I have following 4 tables (including two lookup tables)
My intention is Basically first needs to find out what are the matching records
between ModTab and MedTab through link keys (ItemID & TrfCode through Lookup1) and then
missing OptCodes in MedTab which are in ModTab and viceversa.
Can I do this with one go
Key fields are the one with same name.
When linking MedTab & Lookup2 needs to use both StateCode and OptCode
ModTab
======
Component
Item ID
MedTab
======
TrfCode
OptCode
StateCode
Lookup1
=======
Item ID
TrfCode
Lookup2
========
Component
StateCode
OptCode
How should I do it
Appreciate your guidence
Cheers
Shabar
I think you can achieve this using a FULL JOIN, although I'm pretty hazy on the exact workings of your schema, somehting along the lines of this should work:
SELECT COALESCE(ModTab.ItemID, MedTab.ItemID) AS ItemID,
COALESCE(ModTab.TrfCode, MedTab.TrfCode) AS TrfCode,
COALESCE(ModTab.Component, MedTab.Component) AS Component,
COALESCE(ModTab.StateCode, MedTab.StateCode) AS StateCode,
COALESCE(ModTab.OptCode, MedTab.OptCode) AS OptCode,
CASE WHEN ModTab.OptCode IS NULL THEN 'MedTab Only'
WHEN MedTab.OptCode IS NULL THEN 'ModTab Only'
ELSE 'Both Tables'
END AS MatchStatus
FROM ( SELECT l1.ItemID,
l1.TrfCode,
l2.Component,
l2.StateCode,
l2.OptCode
FROM ModTab m
INNER JOIN Lookup1 l1
ON l1.ItemID = m.ItemID
INNER JOIN Lookup2 l2
ON l2.Component = m.Component
) ModTab
FULL JOIN
( SELECT l1.ItemID,
l1.TrfCode,
l2.Component,
l2.StateCode,
l2.OptCode
FROM MedTab m
INNER JOIN Lookup1 l1
ON l1.TrfCode = m.TrfCode
INNER JOIN Lookup2 l2
ON l2.StateCode = m.StateCode
AND l2.OptCode = m.OptCode
) MedTab
ON ModTab.ItemID = MedTab.ItemID
AND ModTab.TrfCode = MedTab.TrfCode
AND ModTab.Component = MedTab.Component
AND ModTab.StateCode = MedTab.StateCode
AND ModTab.OptCode = MedTab.OptCode;
Some of the joins may need to be amended, but the principle is there, basically full join the data sets, this will return all the records from each, where one is null you know there record is not in that set, where both are not null you know the record is in both.
EDIT
MS-Access does not support FULL JOIN and has a different JOIN syntax for multiple joins so you will have to use UNION to merge the records, then check where the record source is. Something like this should do it:
SELECT ItemID,
TrfCode,
Component,
StateCode,
OptCode,
IIF(SUM(MedTab)=0,'ModTab',IIF(SUM(ModTab)=0,'MedTab','Both')) AS TabStatus
FROM ( SELECT Lookup1.ItemID,
Lookup1.TrfCode,
Lookup2.Component,
Lookup2.StateCode,
Lookup2.OptCode,
1 AS MedTab,
0 AS ModTab
FROM ( MedTab
INNER JOIN Lookup1
ON Lookup1.TrfCode = MedTab.TrfCode
)
INNER JOIN Lookup2
ON Lookup2.StateCode = MedTab.StateCode
AND Lookup2.OptCode = MedTab.OptCode
UNION ALL
SELECT Lookup1.ItemID,
Lookup1.TrfCode,
Lookup2.Component,
Lookup2.StateCode,
Lookup2.OptCode,
0 AS MedTab,
1 AS ModTab
FROM ( ModTab
INNER JOIN Lookup2
ON ModTab.Component = Lookup2.Component
)
INNER JOIN Lookup1
ON ModTab.ItemID = Lookup1.ItemID
)
GROUP BY ItemID, TrfCode, Component, StateCode, OptCode;
I haven't tested this and it is a while since I did any queries in access so fingers crossed it works first time!