Self Join with on different tables - sql

I wrote the following query:
SELECT R1.RELATIONSHIP_ID, R1.SUPPLIER_ACCOUNT_ID, R2.BUYER_ACCOUNT_ID
FROM RELATIONSHIP R1 JOIN RELATIONSHIP R2
ON (R1.RELATIONSHIP_ID = R2.RELATIONSHIP_ID)
ORDER BY SUPPLIER_ACCOUNT_ID;
For the tables:
1. RELATIONSHIP: Columns: RELATIONSHIP_ID, SUPPLIER_ACCOUNT_ID, BUYER_ACCOUNT_ID ...
2. ACCOUNT: ACCOUNT_ID, XX_ACCOUNT_ID ....
and gives the result correctly so far
However, what I want is more complicated. I need to replace the second and third columns with a column called XX_ACOUNT_ID to be shown twice. Each SUPPLIER_ACCOUNT_ID and BUYER_ACCOUNT_ID has a unique XX_ACCOUNT_ID and a unique ACCOUNT_ID. XX_ACCOUNT_ID belongs to the table ACCOUNTS in which there is ACCOUNT_ID (SUUPLIER_ACCOUNT_ID & BUYER_ACCONT_ID are referenced from this column) and XX_ACCOUNT_ID. I'm a bit confused that does it need nested self-join or multiple inner joins? or subqueries to solve this?

If R1.Supplier_Account_ID and R2.Buyer_Account_ID will always exist in the referenced tables, multiple inner joins should work. Try something like this:
SELECT R1.RELATIONSHIP_ID, AcctSupp.XX_ACOUNT_ID, AcctBuyer.XX_ACOUNT_ID
FROM RELATIONSHIP R1
JOIN RELATIONSHIP R2 ON (R1.RELATIONSHIP_ID = R2.RELATIONSHIP_ID)
JOIN Accounts AcctSupp ON R1.SUPPLIER_ACCOUNT_ID = AcctSupp.Account_ID
JOIN Accounts AcctBuyer ON R2.BUYER_ACCOUNT_ID = AcctBuyer.Account_ID
ORDER BY SUPPLIER_ACCOUNT_ID;
If there's any chance the values won't exist in the referenced tables, use left joins instead:
SELECT R1.RELATIONSHIP_ID, AcctSupp.XX_ACOUNT_ID, AcctBuyer.XX_ACOUNT_ID
FROM RELATIONSHIP R1
JOIN RELATIONSHIP R2 ON (R1.RELATIONSHIP_ID = R2.RELATIONSHIP_ID)
LEFT JOIN Accounts AcctSupp ON R1.SUPPLIER_ACCOUNT_ID = AcctSupp.Account_ID
LEFT JOIN Accounts AcctBuyer ON R2.BUYER_ACCOUNT_ID = AcctBuyer.Account_ID
ORDER BY SUPPLIER_ACCOUNT_ID;

Perhaps I misunderstood the question, but I don't see why you need a self join:
SELECT R.Relationship_Id,
Supplier.xx_account_id sup_id,
Buyer.xx._account_id buy_id
FROM Relationship AS R
JOIN Accounts AS Buyer
ON R.Buyer_account_Id = Buyer.Account_Id
JOIN Accounts AS Supplier
ON R.Supplier_account_Id = Supplier.Account_Id

Related

How to join 4 tables in SQL?

I just started using SQL and I need some help. I have 4 tables in a database. All four are connected with each other. I need to find the amount of unique transactions but can't seem to find it.
Transactions
transaction_id pk
name
Partyinvolved
transaction.id pk
partyinvolved.id
type (buyer, seller)
PartyCompany
partyinvolved.id
Partycompany.id
Companies
PartyCompany.id pk
sector
pk = primary key
The transaction is unique if the conditions are met.
I only need a certain sector out of Companies, this is condition1. Condition2 is a condition inside table Partyinvolved but we first need to execute condition1. I know the conditions but do not know where to put them.
SELECT *
FROM group
INNER JOIN groupB ON groupB.group_id = group.id
INNER JOIN companies ON companies.id = groupB.company_id
WHERE condition1 AND condition2 ;
I want to output the amount of unique transactions with the name.
It is a bit unclear what you are asking as your table definitions look like your hinting at column meanings more than names such as partycompany.id you are probably meaning the column that stores the relationship to PartyCompany column Id......
Anyway, If I follow that logic and I look at your questions about wanting to know where to limit the recordsets during the join. You could do it in Where clause because you are using an Inner Join and it wont mess you your results, but the same would not be true if you were to use an outer join. Plus for optimization it is typically best to add the limiter to the ON condition of the join.
I am also a bit lost as to what exactly you want e.g. a count of transactions or the actual transactions associated with a particular sector for instance. Anyway, either should be able to be derived from a basic query structure like:
SELECT
t.*
FROM
Companies co
INNER JOIN PartyCompancy pco
ON co.PartyCompanyId = pco.PartyCompanyId
INNER JOIN PartyInvolved pinv
ON pco.PartyInvolvedId = pinv.PartyInvolvedId
AND pinv.[type] = 'buyer'
INNER JOIN Transactions t
ON ping.TransactionId = t.TransactionId
WHERE
co.sector = 'some sector'

SQL for many to one to many table

I have three tables in an Access database that I am using in java via ucanaccess.
Patients (PK Pt_ID)
Endoscopy (PK Endo_ID, FK Pt_ID)
Histology (PK Histol_ID, FK Pt_ID)
1 patient can have many endoscopies
1 patient can have many histologies
Endoscopy and histology are not related
I want to retrieve all the Endoscopies and histologies for a single patients in a single SQL query. Although I can write select statements for two tables I don't know how to do this across the three tables. Is it something like this
Select *.Endoscopy,*.Histology from Patients INNER JOIN Endoscopy, Histology ON Patient.Pt_Id=Endoscopy.Pt_ID, Patient.Pt_Id=Histology.Pt_ID
I'm sure that's a mess though...
What kind of SQL DB are you using?
I believe this works on most.
SELECT * FROM Patients, Endoscopy, Histology
WHERE Patient.Pt_Id=Endoscopy.Pt_ID
AND Patient.Pt_Id=Histology.Pt_ID
Also, I belive you have these switched around *.Endoscopy,*.Histology If you need to use that it should be Endoscopy.*, Histology.*
You can use the following query to select both endoscopies and histologies :
SELECT p.Pt_ID
, e.Endo_ID
, h.Histol_ID
FROM Patients p
INNER JOIN Endoscopy e ON p.Pt_Id = e.Pt_ID
INNER JOIN Histology h ON p.Pt_Id = h.Pt_ID
But I'm not sure this is really what you want. You might need to map the tables Patients, Endoscopy and Histology into Java classes ? In this case, you can consider the Java Persistence API (JPA). It helps you to handle these tables in your java code. Here is a JPA Quick Guide.
First idea is to use inner join (with correct syntax) but this is wrong. inner join returns patients who have both procedure. Pure left join returns additionally patients who have none. So this is the solution:
SELECT Patients.Pt_PK, Endoscopy.*, Histology.*
FROM Patients
LEFT JOIN Endoscopy ON Patients.Pt_Id = Endoscopy.Pt_ID
LEFT JOIN Histology ON Patients.Pt_Id = Histology.Pt_ID
--exclude patients who don't have any
where coalesce(Endoscopy.Endo_ID, Histology.Histol_ID) is not null
If you have multiple Endoscopy records or multiple Histology records for the same Patient then you will receive duplicate/repeated records in your SELECT. I do no think there is a way around that unless you use 2 SELECT statements instead of 1.
SELECT Endoscopy.*, Histology.*
FROM Patients
INNER JOIN Endoscopy ON Patients.Pt_Id = Endoscopy.Pt_ID
INNER JOIN Histology ON Patients.Pt_Id = Histology.Pt_ID
To select all records on a table in the select its table name/table alias .*
INNER JOIN will only select records where there is a relationship, once one of these tables does not contain a Pt_ID where it is contained in any one of the other tables then no record will be displayed with that Pt_ID
To add additional tables continue to add additional join statements
You used Patients (with S) in one location and Patient (no S) in another, make sure you use the correct naming. I am guessing its Patients but maybe its Patient.
This statement does almost the same as the above but uses LEFT JOIN syntax so that you will always get records for both tables even if one of the two tables does not have a record for a patient.
SELECT Endoscopy.*, Histology.*
FROM Patients
LEFT JOIN Endoscopy ON Patients.Pt_Id = Endoscopy.Pt_ID
LEFT JOIN Histology ON Patients.Pt_Id = Histology.Pt_ID
WHERE Histology.Histol_ID IS NOT NULL OR Endoscopy.Endo_ID IS NOT NULL
The added WHERE clause ensures that you do not get a record with all NULL values where there is a patient but no records in either of those tables.

SQL Server : join tables causes the data to duplicate on every row

I have this query which is returning some redundant data. Can somebody please help me to correct this query. I have also attached the table relationship.
SELECT
dbo.supplierOrder.sectionID,
dbo.supplierOrder.supplierID,
dbo.supplierOrder.supplierOrderNo,
dbo.supplierOrder.supplierOrderCreated,
dbo.supplierOrder.supplierOrderConfirmStatus,
dbo.supplierOrderDetails.productID,
dbo.supplierOrderDetails.orderQty,
dbo.supplierOrderReceive.invoiceno,
dbo.supplierOrderReceive.supplierInvoiceno,
dbo.supplierOrderReceive.ID,
dbo.supplierOrderReceiveDetail.qtyArrived
FROM
dbo.supplierOrder
INNER JOIN
dbo.supplierOrderDetails ON (dbo.supplierOrderDetails.supplierOrderID = dbo.supplierOrder.ID)
INNER JOIN
dbo.supplierOrderReceive ON (dbo.supplierOrderReceive.supplierOrderID = dbo.supplierOrder.ID)
INNER JOIN
dbo.supplierOrderReceiveDetail ON (dbo.supplierOrderReceiveDetail.supplierOrderReceiveID = dbo.supplierOrderReceive.ID)
WHERE
dbo.supplierOrder.ID = 1 ;
here is the output that I get
which is not exactly what I was want. the last column qtyArrived should show only its related qty but here as you can see it is repeating for each of the productID
and here is the db tables and relationship
I think the last table should be join using also ProductId not only OrderID :
LEFT JOIN
dbo.supplierOrderReceiveDetail
ON
(dbo.supplierOrderReceiveDetail.supplierOrderReceiveID=dbo.supplierOrderReceive.ID)
AND
(dbo.supplierOrderReceiveDetail.ProductID =dbo.sdbo.supplierOrderDetails.ProductID)

SQL fetch multiple values on join

Hi I have an SQL table which has two tables which make reference to the same foreign key in a separate table twice... something like
SALES table
idSales idClient1 idClient2
1 1 2
CLIENT table
idClient ClientName
1 Bob
2 Mick
I want to join the SALES table to the CLIENT table and return data as follows:
idSales idClientClientName1 idClientClientName2
1 Bob Mick
Can anyone help with the SQL for this? I'm getting ambiguous column name errors on my join.
Thank you
You need to basically join table Client on table Sales twice because there are two columns on table Sales that are dependent on table Client.
SELECT a.idSales,
b.ClientName ClientName1,
c.ClientName ClientName2
FROM Sales a
INNER JOIN Client b
ON a.idClient1 = b.idClient
INNER JOIN Client c
ON a.idClient2 = c.idClient
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins
But when one of the columns or both columns are nullable, INNER JOIN will not give you all records from Sales because it will only select where it has atleast one match on the other table. Instead use LEFT JOIN.
I might add that in cases like this, I use table aliases that hint at what entity you are linking to in the joined table. If for example, the foreign keys were to an address table, and you had a work address, and a Home address, I would use tables aliases of h and w for the two joins. In your case, i.e.,
Selext s.idSales,
c1.ClientName ClientName1,
c2.ClientName ClientName2
From Sales s
Join Client c1
On c1.idClient = s.idClient1
Join Client c2
On c2.idClient = s.idClient2
For those beginner SQL folks who may see this question in the future, it's helpful to add in the AS words, it makes it clearer still:
SELECT
Sale.idSales,
c1.ClientName AS ClientName1,
c2.ClientName AS ClientName2
FROM
Sales AS Sale
INNER JOIN Client AS c1 ON Sale.idClient1 = c1.idClient
INNER JOIN Client AS c2 ON Sale.idClient2 = c2.idClient

Retrieve different row from same table

i hava a set of following tables
customer(cus_id,cus_name);
jointAccount(cus_id,acc_number,relationship);
account(acc_number,cus_id)
now i want to create a select statement to list all the jointAccounts,
it should included the both customer name, and relationship.
I have no idea how to retrieve both different user name, is that possible to do this?
Generally speaking, yes. I'm assuming you mean you want to get customer info for both sides of the joint account per your jointAccount table. Not sure what database you're using so this answer is assuming MySQL.
You can join on the same table twice in a single SQL query. I'm assuming you have not yet created your tables, as you have cus_id listed twice in the jointAccount table. Typically these would be something like cus_id1 and cus_id2, which I've used in my sample query below.
Example:
SELECT c1.cus_id AS cust1_id, c1.cus_name AS cust1_name
, c2.cus_id AS cust2_id, c2.cus_name AS cust2_name, j.relationship
FROM customer c1
INNER JOIN jointAccount j
ON c1.cus_id = j.cus_id1
, customer c2
INNER JOIN jointAccount j
ON c2.cus_id = j.cus_id2
I haven't tested this but that's the general idea.
try this query:
SELECT * FROM jointAccount a LEFT JOIN customer c ON a.cus_id = c.cus_id;
just replace the * with the name of the columns you need.