I have 3 tables (user, user_authority_rules_history & authority_rules_history) I want to select values from two of the tables if they match my criterias.
My query looks like this
SELECT
user_authority_rules_history.download_date,
authority_rules_history.*
FROM
user_authority_rules_history,
authority_rules_history
LEFT JOIN
user_authority_rules_history
ON
user_authority_rules_history.authority_rule_id = authority_rules_history.id
LEFT JOIN
user
ON
user_authority_rules_history.user_id = user.id
WHERE
user.id = 1
Im able make it work, if i leave out user_authority_rules_history.download_date from my query, but then im obviously missing that data. What am i doing wrong here ?
You have an extra table reference to user_authority_rules_history in the from clause. A simple rule: never use commas in the from clause.
I think this is what you intend:
SELECT user_authority_rules_history.download_date,
authority_rules_history.*
FROM authority_rules_history LEFT JOIN
user_authority_rules_history
ON user_authority_rules_history.authority_rule_id = authority_rules_history.id LEFT JOIN
user
ON user_authority_rules_history.user_id = user.id
WHERE user.id = 1
Note that you are filtering on user.id = 1. This is undoing your left join, so you might as well use inner join on the tables. I am not sure what you really intend, but this should fix your problem.
Related
in query here i have https://www.db-fiddle.com/f/32Kc3QisUEwmSM8EmULpgd/1
SELECT p.prank, d.dare
FROM dares d
INNER JOIN pranks p ON p.id = d.prank_id
WHERE d.condo_id = 1;
i have one condo with id 1 and it have unique connection to dares that has connection to pranks and unique connection to condos_pranks
and i wanna have all unique pranks from both tables and i used this query above to get relation of
dares to pranks and expected result was L,M,N - Yes,No,Maybe and it is correct but i also wanna have those in condos_pranks which ids are 1,4,5,6 = L,O,P,Q
so i tried to join the table with left join because it might not have condos_pranks row
SELECT p.prank, d.dare
FROM dares d
INNER JOIN pranks p ON p.id = d.prank_id
LEFT JOIN condos_pranks pd ON pd.condo_id = d.condo_id AND pd.prank_id = p.id
WHERE d.condo_id = 1;
but result is same as first and what i want is
prank
dare
L
Yes
M
No
N
Maybe
O
No
P
No
Q
No
with default being No = 2 if prank_id of condos_pranks is not in dares
how to connect it?
This seems like an exercise in identifying extraneous information more than anything. You are unable to join something to a table that has no key, however if you know your default then you may use something like coalesce to identify the records where there was no data to join NULL and replace them with your default.
I mentioned in a comment above that this table schema makes little sense. You have keys all over the place that doing have all sorts of circular references. If this is your derived schema, consider stopping here and revisiting the relationships. If it is not and it is something educational, which I suspect it is, disregard and recognize the logical flaws in what you are working in. Perhaps consider taking the data provided and creating a new table schema that is more normalized and uses other tables to handle the many to many and one to many relationships.
dbfiddle
SELECT
pranks.prank,
COALESCE(dares.dare, 'No')
FROM pranks LEFT OUTER JOIN
dares ON pranks.id = dares.prank_id
ORDER BY pranks.prank ASC;
clearlyclueless gave correct explanations
To achieve the result, the following SELECT can also be used:
SELECT
pranks.prank,
case
when dare is null then 'No'
else dare
end
FROM pranks LEFT OUTER JOIN
dares ON pranks.id = dares.prank_id
I'm populating a table which is fetching the ids from 2 other tables to display their information, for example, delivery has a Hamburguer and the box, but the user might register the delivery with out the box, only with the hamburguer.
When I make a INNER JOIN SELECT to get the data from the DB it will return 0 results since there is no box and I'm trying to compare the ids that don't exist. It doesn't populate the table then.
SELECT
entrega_telemovel.*,
telemovel.id_telemovel,
telemovel.nroserie,
nro_telemovel.numero_telemovel,
nro_telemovel.id_nrotelemovel,
funcionarios.id_funcionario,
funcionarios.nome
FROM entrega_telemovel
INNER JOIN telemovel
ON entrega_telemovel.telemovel = telemovel.id_telemovel
INNER JOIN nro_telemovel
ON nro_telemovel.id_nrotelemovel = entrega_telemovel.numero_telemovel
INNER JOIN funcionarios
ON funcionarios.id_funcionario = entrega_telemovel.funcionario_entrega
ORDER BY funcionarios.nome;
In this query above entrega_telemovel.telemovel=telemovel.id_telemovel the value in entrega_telemovel.telemovel is null like the example I gave above. So 0 results are returned from the query.
How can I solve this ?
You are looking for a LEFT JOIN.
INNER JOIN only combines rows, that exist in both tables. A LEFT JOIN on the other hand always produces at least one row. If on table does not have a match for it, all columns are set to NULL.
SELECT
entrega_telemovel.*,
telemovel.id_telemovel,
telemovel.nroserie,
nro_telemovel.numero_telemovel,
nro_telemovel.id_nrotelemovel,
funcionarios.id_funcionario,
funcionarios.nome
FROM entrega_telemovel
LEFT JOIN telemovel
ON entrega_telemovel.telemovel = telemovel.id_telemovel
LEFT JOIN nro_telemovel
ON nro_telemovel.id_nrotelemovel = entrega_telemovel.numero_telemovel
LEFT JOIN funcionarios
ON funcionarios.id_funcionario = entrega_telemovel.funcionario_entrega
ORDER BY funcionarios.nome;
You want to show all entrega_telemovel entries, no matter whether they have a match in entrega_telemovel or not. This is what an outer join does.
SELECT ...
FROM entrega_telemovel et
LEFT OUTER JOIN telemovel t ON et.telemovel = t.id_telemovel
...
I wrote a query that join 3 tables :
SELECT `notification`.`nid`, `notification`.`type`, `notification`.`read`, `notification`.`time`, `user`.`pro_img`, `user`.`fname` ,`user`.`lname`, `user`.`username`, `accommodation`.`aid`, `accommodation`.`title`, `accommodation`.`home_img`
FROM `notification` RIGHT OUTER JOIN `user` ON `notification`.`rid`=`user`.`id` RIGHT OUTER JOIN `accommodation` ON `notification`.`acco_id`=`accommodation`.`aid`
WHERE `notification`.`uid`=$uid ORDER BY `notification`.`time` DESC;
i want to have result while notification.acco_id= accommodation.aid is not found so empty columns is ok but i want rows
Your query is combining a few things that don't go along. The right joins you are using will preserve anything that's in the right side tables, in your case user and accomodation, but using two of them with the same left side will make this useless. You also have a condition in your where involving the left side of the joins, and this also will make the right joins pointless.
Assuming you want all the notifications, regardless of them being matched with users and accomodations or not, you only need to change from right to left joins.
SELECT notification.nid,
notification.type,
notification.read,
notification.time,
user.pro_img,
user.fname,
user.lname,
user.username,
accommodation.aid,
accommodation.title,
accommodation.home_img
FROM notification
LEFT OUTER JOIN
user
ON notification.rid = user.id
LEFT OUTER JOIN
accommodation
ON notification.acco_id = accommodation.aid
WHERE notification.uid = $uid
ORDER BY notification.time DESC
This will preserve all the rows in notification, and will match them with null values when there are no matching rows on the other table(s).
This is my structure of tables:
tables_structure
and there's tbl_owner, tbl_rooms and tbl_class.
How do I get id_class and class name from tbl_class.
The original source code is like this:
SELECT
clas.id_class,
clas.class_name
FROM
tbl_rooms AS room
LEFT JOIN tbl_class AS clas ON room.id_class = clas.id_class
LEFT JOIN tbl_owner AS own ON room.id_owner = own.id_owner
WHERE own.id_owner='1';
However, it did not work. Please help me?
SELECT
clas.id_class,
clas.class_name
FROM
tbl_rooms AS room
LEFT JOIN tbl_class AS clas ON room.id_class = clas.id_class
LEFT JOIN tbl_owner AS own ON room.id_owner = own.id_owner
WHERE own.id_owner='1';
Left Joins and wheres can be a little confusing.
Here you are asking for all rooms and if they have a class return it, it they have an owner return it. Which is done by the left join.
Then after getting that info, Your asking to filter the results by owner = 1
Given that there were left joins used to build this data, you have now said only show the results where both joins matched. Effectively turning the left join to an inner join.
I would take away the where clause and check the join conditions are producing results you expect first, then start to allow the where to narrow the result set.
The correct way to check if a left join is a condition is (own.id_owner='1') OR (own.id_owner is null)
That will bring back all owner = 1 and all unknown owners
I was desperately trying harder and harder to get this thing done but didn`t yet succeed. I am getting repeated values when i run this query.
select
tbl_ShipmentStatus.ShipmentID
,Tbl_Contract.ContractID,
Tbl_Contract.KeyWinCountNumber,
Tbl_Item.ItemName,
Tbl_CountryFrom.CountryFromName,
Tbl_CountryTo.CountryToName,
Tbl_Brand.BrandName,
Tbl_Count.CountName,
Tbl_Seller.SellerName,
Tbl_Buyer.BuyerName,
Tbl_Contract.ContractNumber,
Tbl_Contract.ContractDate,
tbl_CountDetail.TotalQty,
tbl_CostUnit.CostUnitName,
tbl_Comission.Payment,
tbl_Port.PortName,
Tbl_Contract.Vans,
tbl_Comission.ComissionPay,
tbl_Comission.ComissionRcv,
tbl_CountDetail.UnitPrice,
tbl_Comission.ComissionRemarks,
tbl_CountDetail.Amount,
tbl_LCStatus.LCNumber,
tbl_ShipmentStatus.InvoiceNumber,
tbl_ShipmentStatus.InvoiceDate,
tbl_ShipmentStatus.BLNumber,
tbl_ShipmentStatus.BLDate,
tbl_ShipmentStatus.VesselName,
tbl_ShipmentStatus.DueDate
from tbl_ShipmentStatus
inner join tbl_LCStatus
on
tbl_LCStatus.LCID = tbl_ShipmentStatus.LCStatusID
inner join Tbl_Contract
on
tbl_LCStatus.ContractID = Tbl_Contract.ContractID
inner join Tbl_CountDetail
on Tbl_Contract.ContractID = Tbl_CountDetail.ContractId
inner join tbl_Comission
on
tbl_Comission.ContractID = Tbl_Contract.ContractID
inner join Tbl_Item
on
Tbl_Item.ItemID = Tbl_Contract.ItemID
inner join Tbl_Brand
on Tbl_Brand.BrandID = Tbl_Contract.BrandID
inner join Tbl_Buyer
on Tbl_Buyer.BuyerID = Tbl_Contract.BuyerID
inner join Tbl_Seller
on Tbl_Seller.SellerID = Tbl_Contract.SellerID
inner join Tbl_CountryFrom
on Tbl_CountryFrom.CountryFromID = Tbl_Contract.CountryFromID
inner join Tbl_CountryTo
on
Tbl_CountryTo.CountryToID = Tbl_Contract.CountryToID
inner join Tbl_Count
on
Tbl_Count.CountID = Tbl_CountDetail.CountId
inner join tbl_CostUnit
on tbl_Comission.CostUnitID = tbl_CostUnit.CostUnitID
inner join tbl_Port
on tbl_Port.PortID = tbl_Comission.PortID
where tbl_LCStatus.isDeleted = 0
and tbl_ShipmentStatus.isDeleted =0
and tbl_LCStatus.isDeleted = 0
and Tbl_CountDetail.isDeleted = 0
and Tbl_Contract.isDeleted = 0
and tbl_ShipmentStatus.LCStatusID = 5
I have also attached a picture of my result set of rows.
Any suggestions why this is happening would really be appreciable.
Result Set
Typically this happens when you have an implicit partial cross join (Cartesian product) between two of your tables. That's what it looks like to me here.
This happens most often when you have a many-to-many relationship. For example, if a single Album allows both multiple Artists and multiple Songs and the only relationship between Artists and Songs is Album, then there's essentially a many-to-many relationship between Artists and Songs. If you select from all three tables at once you're going to implicitly cross join Artists and Songs, and this may not be what you want.
Looking at your query, I see many-to-many between Tbl_CountDetail and tbl_Comission through Tbl_Contract. Try eliminating one of those joins to test to see if the behavior disappears.
Try using the DISTINCT keyword. It should solve your issue
Select DISTINCT ....
Wait as far as I can see your records are not duplicates.
HOWEVER
Notice the CountName column and Shipment ID column
The combination is unique for every row. Hence the values are unique as far as I can see. Try not selecting CountName.
Well if you have distinct rows its not a duplication problem. The issue is during the join a combination is occurring you don't want it to duplicating the results.
Either don't select CountName or you have a mistake in your data.
Only one of those rows should be true either 6 with Count2 or 6 with Count1. Likewise for 7. The fact that your getting both when your not supposed to indicates a logic mistake