How to use JOIN correctly - sql

Can someone help me with this? I am new to SQL.
I want to return one record for every record in Product_Entity.
Product_Entity is linked to Entity_Varchar by the common coilumn entity_id.
I want each record in the results to include Entity_Varchar.value, but only when Entity_Varchar.attribute_id = ‘73’ as there will be many records in Entity_Varchar that will match on entity_id, but only one where also Entity_Varchar.attribute_id=’73’
SELECT
Product_Entity.sku AS SKU,
Entity_Varchar.value AS Description
FROM
Product_Entity
JOIN
Entity_Varchar ON Entity_Varchar.entity_id = Entity_Varchar.entity_id
WHERE
Entity_Varchar.attribute_id = '73'

Your query basically looks right. However, if you want all rows in the first table, then use a LEFT JOIN:
SELECT pe.sku AS SKU, ev.value AS Description
FROM Product_Entity pe LEFT JOIN
Entity_Varchar ev
ON ev.entity_id = pe.entity_id AND
ev.attribute_id = '73';
Rows that don't match will have NULL for the description.

Your query is correct you just misspelled table name. Instead of Product_Entity you used Entity_Varchar in both side of on clause.
Corrected query:
SELECT Product_Entity.sku AS SKU, Entity_Varchar.value AS Description FROM Product_Entity inner Join Entity_Varchar
ON Product_Entity.entity_id = Entity_Varchar.entity_id
WHERE Entity_Varchar.attribute_id = '73'
For better readability you can use table aliaces.
SELECT pe.sku AS SKU, ev.value AS Description
FROM Product_Entity pe inner Join Entity_Varchar ev
ON pe.entity_id = ev.entity_id
WHERE ev.attribute_id = '73'
If you want to select rows from Product_Entity table even when there is no row in Entity_Varchar table with same entity_id and for attribute_id 73 you need to use left join instead of inner join.
SELECT pe.sku AS SKU, ev.value AS Description
FROM Product_Entity pe left Join Entity_Varchar ev
ON pe.entity_id = ev.entity_id
WHERE ev.attribute_id = '73'

If I understand you need, you want every record from Product_Entity, whether or not it has an attribute_id = 73 record on Entity_Varchar. But if there is an attibute_id = 73 record on Entity_Varchar, you want the description from that row also.
First, you need a LEFT OUTER JOIN to get all of the records from Product_Entity, not filtered by the contents of Entity_Varchar.
Then, you need to filter Entity_Varchar. But if you place this filter in the WHERE clause, it causes the join to become an INNER JOIN. (I see error a lot. I call it a "LEFT INNER JOIN". Of course, that's not a real thing.) To overcome this, put the filter in the join logic. Then it's filtered before being joined.
SELECT Product_Entity.sku AS SKU
, Entity_Varchar.value AS Description
FROM Product_Entity
LEFT OUTER JOIN Entity_Varchar ON Entity_Varchar.entity_id = Entity_Varchar.entity_id
AND Entity_Varchar.attribute_id = '73'

Your query is correct you just misspelled table name. Instead of Product_Entity you used Entity_Varchar in both side of on clause.
SELECT Product_Entity.sku AS SKU, Entity_Varchar.value AS Description FROM Product_Entity inner Join Entity_Varchar
ON Product_Entity.entity_id = Entity_Varchar.entity_id
WHERE Entity_Varchar.attribute_id = '73'

Related

Select and join returning duplicate data

I have some tables that can be accessed here and I would like to get a new table with EntryId from Entry table and ProtocolNumber from JudicialOrder table. For that I'm using this query:
SELECT DISTINCT ET.EntryId, JOA.ProtocolNumber FROM Entry AS ET
LEFT JOIN JudicialOrderAccount AS JOT ON JOT.AccountId = ET.OwnerAccountId
INNER JOIN JudicialOrder AS JOA ON JOA.JudicialOrderId = JOT.JudicialOrderId;
But the ProtocolNumber is duplicated, what could be wrong with my query?
As Kurt said only the combination of ET.EntryId, JOA.ProtocolNumber is unique. You will recognize it if you add an order by.
SELECT DISTINCT ET.EntryId, JOA.ProtocolNumber FROM Entry AS ET
LEFT JOIN JudicialOrderAccount AS JOT ON JOT.AccountId = ET.OwnerAccountId
INNER JOIN JudicialOrder AS JOA ON JOA.JudicialOrderId = JOT.JudicialOrderId
ORDER BY ET.EntryId, JOA.ProtocolNumber;
If you would really like to have unique protocol number you would need to group by ProtocolNumber and wrap EntryId in some string_agg function (depends on your database).
FYI: Your LEFT JOIN - INNER JOIN combination ends up being two INNER JOINs, see

Get all the values from the first left table but when two left joins used its restricting the values from first table

I am trying to get all the values from the first left table but when I use two left joins its restricting the values from first table.
I used the below query
SELECT P.person_id, TS.Task_Id, TS.skill
FROM Person P
LEFT JOIN Person_Skill PS ON P.person_id = PS.person_id
LEFT JOIN Task_Skill TS ON PS.Skill = TS.Skill
WHERE ts.task_id = 245
I need all the person id from person table.
Just move the condition on the left joined table from the where clause to the on clause of the join:
select p.person_id, ts.task_id, ts.skill
from person p
left join person_skill ps
on p.person_id = ps.person_id
left join task_skill ts
on ps.skill = ts.skill
and ts.task_id = 245 --> here
Rationale: conditions in the where clause are mandatory. If there is no match in ts, then condition ts.task_id = 245 cannot be satisfied, since ts.task_id is null.
Use the filter condition in a sub query instead of using it as a global filter outside. This should give you the output that you desire.
SELECT P.person_id,TS.Task_Id,TS.skill FROM Person P
LEFT JOIN Person_Skill PS
ON P.person_id=PS.person_id
LEFT JOIN
(Select * from Task_Skill where task_id = 245) TS
ON PS.Skill=TS.Skill;

Left Outer Join Without Duplicate Rows

After a lot of searching I could not solve my problem. I have the following tables:
I want to select all records from my 'product' table. but I have a problem. I got multiple rows from 'product' table when I execute the following query:
SELECT dbo.product.id, dbo.product.name, dbo.product_price.value
dbo.product_barcode.barcode
FROM dbo.product LEFT OUTER JOIN
dbo.product_price ON dbo.product.id = dbo.product_price.product_id LEFT OUTER JOIN
dbo.product_barcode ON dbo.product.id = dbo.product_barcode.product_id
My problem was solved with the following query:
SELECT dbo.product.id, dbo.product.name, dbo.product_price.value
dbo.product_barcode.barcode
FROM dbo.product LEFT OUTER JOIN
dbo.product_price ON dbo.product.id = dbo.product_price.product_id LEFT OUTER JOIN
dbo.product_barcode ON dbo.product.id = dbo.product_barcode.product_id
WHERE (dbo.product_price.id IN
(SELECT MIN(id) AS minPriceID
FROM dbo.product_price AS product_price_1
GROUP BY product_id)) AND (dbo.product_barcode.id IN
(SELECT MIN(id) AS Expr1
FROM dbo.product_barcode AS product_barcode_1
GROUP BY product_id))
Now I have just one problem. if the 'product_price' table or 'product_barcode' table does not have any record, No records will be returned. I mean if no similar record is found in 'product_price' or 'product_barcode' table, we will not have any record. while we should have records from the 'product' table with null columns of other tables.
Please help me Thanks.
I think the problem is that the conditions are in the WHERE clause - try moving the conditions from the WHERE clause and into each join:
SELECT dbo.product.id, dbo.product.name, dbo.product_price.value,
dbo.product_barcode.barcode
FROM dbo.product
LEFT OUTER JOIN dbo.product_price ON dbo.product.id = dbo.product_price.product_id
--moved from WHERE clause
AND dbo.product_price.id IN (SELECT MIN(id) AS minPriceID FROM dbo.product_price AS product_price_1 GROUP BY product_id)
LEFT OUTER JOIN dbo.product_barcode ON dbo.product.id = dbo.product_barcode.product_id
--moved from WHERE clause
AND dbo.product_barcode.id IN (SELECT MIN(id) AS Expr1 FROM dbo.product_barcode AS product_barcode_1 GROUP BY product_id)
SELECT dbo.product.id, dbo.product.name, MIN(dbo.product_price.value),MIN( dbo.product_barcode.barcode)
FROM dbo.product
LEFT OUTER JOIN dbo.product_price ON dbo.product.id = dbo.product_price.product_id
LEFT OUTER JOIN dbo.product_barcode ON dbo.product.id = dbo.product_barcode.product_id
GROUP BY dbo.product.id, dbo.product.name
While the above query should achieve your desired results - one entry for product with the minimun product_price (if one exist) and minimum product_barcode (if one exist).
I only assumed you wanted this based on the query you were writing. You need to spend more time thinking about the question you are trying to answer.
Joining will multiply your results if more than one entry per join key is present in one of the tables.
Just remember this diagram:
When you are calling LEFT JOIN and applying filtering like in the second picture from the top left, you will get only items belonging to the A table.
I want to select all records from my 'product' table. but I have a problem. I got multiple rows from 'product' table when I execute the following query:
Can you try calling DISTINCT after SELECT, like this:
SELECT DISTINCT dbo.product.id, dbo.product.name, dbo.product_price.value
dbo.product_barcode.barcode
...

How to join multiple tables in a view

how to create view of this query anyone help me please, i want create view of this but its show me error
Msg 4506, Level 16, State 1, Procedure ordersview, Line 3 Column names
in each view or function must be unique. Column name 'ID' in view or
function 'ordersview' is specified more than once.
CREATE VIEW ordersview
AS
Select * from UserClaimData cd
Inner join UserClaimDeductions ud on
ud.CLAIMID = cd.ID
Inner join UserClaimApproval ua on
ua.CLAIMID = cd.ID
inner join ClaimDataBreakdown cb on
cb.CLAIMID = cd.ID
inner join AppExpenseTypes ae on
ae.ID = cb.EXPENSETYPE
inner join AppNOWTypes an on
ae.ID = an.EXPENSETYPEID
inner join AppAreas aa on
aa.ID = cb.AREAID
inner join AppZones az on
cb.ZONEID = az.ID
inner join AppRegions ar on
ar.ID = cb.REGIONID
The answer to the question you've asked is to specifically reference elements from each table; for example:
CREATE VIEW ordersview
AS
Select cd.ID AS ID1, ua.ID as ID2, etc... from UserClaimData cd
Inner join UserClaimDeductions ud on
ud.CLAIMID = cd.ID
Inner join UserClaimApproval ua on
ua.CLAIMID = cd.ID
inner join ClaimDataBreakdown cb on
cb.CLAIMID = cd.ID
inner join AppExpenseTypes ae on
ae.ID = cb.EXPENSETYPE
inner join AppNOWTypes an on
ae.ID = an.EXPENSETYPEID
inner join AppAreas aa on
aa.ID = cb.AREAID
inner join AppZones az on
cb.ZONEID = az.ID
inner join AppRegions ar on
ar.ID = cb.REGIONID
I would, however, suggest that you don't put such a complex join inside a view. Consider the columns you want, and perhaps think about a stored procedure, or a table value function.
What part of the error message do you not understand?
You have select *, which brings together all columns from all tables. Just based on the join conditions, it is clear that most tables have an ID column, so there are multiple columns called ID. CLAIMID also seems quite popular.
In general, using select * is discouraged. However, it should not be used for views. A view should state the columns that it contains:
select cd.Id, . . .
Your view has more than one column with the same name, and this is causing the error.
AppRegions has a column called ID
AppAreas has a column called ID
UserClaimData has a column called ID
Change the Select * to specify the columns of the tables you want to have on the View table, and put a particularry name, or just don't put them.
You need to change the name of some columns in the view. Use AppAreas.ID as aaID
A view is like a virtual table, So you can't have the same name for 2(or more) columns.
So to avoid this, in your select Query instead of * provide the column names, and if there are 2 columns with the same name and you need them both in the view, give them different alias names.
Suppose you have ColumnA in TableA and TableB and you want them both in the view. Create view like this
CREATE VIEW vm_Sample
SELECT
A.COLUMNA COLUMNA_1,
B.COLUMNA COLUMNA_2
FROM TABLEA A INNER JOIN TABLE B
ON A.ID = B.ID

Adding a condition to an inner join query in Oracle

I have this inner join query:
select *
from ioa_invoice_line
INNER JOIN ioa_invoice
ON ioa_invoice_line.invo_id = ioa_invoice.id ;
Now, I want to add this condition also in the above inner join that is
where ioa_invoice_line.invo_id =234
Please advise how to add this condition in above query.
As Felix says in his comment you can add it without problems:
select *
from ioa_invoice_line
INNER JOIN ioa_invoice
ON ioa_invoice_line.invo_id = ioa_invoice.id
AND ioa_invoice_line.invo_id = 234
As this is criteria on the first table, you would usually simply add this WHERE clause at the end of your query (before the semicolon of course).
However, you are dealing with an invoice table and its detail table here and the criteria is on the key linking the tables. So for readability, I would swap the tables and name the parent table first and join the child table. That feels more natural:
select *
from ioa_invoice i
join ioa_invoice_line il on il.invo_id = i.id
where i.id = 234;
select * from
ioa_invoice_line il
INNER JOIN ioa_invoice i
ON il.invo_id = i.id
where il.invo_id = 234
This format use as a professional practice