how do i join third table values into main join? - mysql

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

Related

Select from two tables gives Not unique table/alias

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.

inner and outer join together in query, possible

i am trying to implement inner and outer join in single query, i am not sure if i am doing the right way or wrong way, as i am not very good with queries.
So here it goes.
I have these following tables.
hrs_residentials
hrs_residential_utilities
hrs_utilities
hrs_utility_type
hrs_residentials:
ResID, ResType, ResNo - - -
1 2 001 - - -
hrs_residential_utilities:
RUID, UtilityID, ResID, - - - -
NULL NULL NULL
hrs_utilities:
UtilityID, UtilityTypeID, Number, ConsumerNumber, -, -, -
NULL NULL NULL NULL
hrs_utility_type:
UTID, UName, UDescription
1 PESCO PESCO Electric Meter
2 SNGPL Sui Northen Gas Pipe Lines
So i want to show in datatables the data, but what i want that data should show in table for hrs_residentials table, dosent matter if hrs_residential_utilities have data or not.
So i went for Left outer join and i got the result i wanted.
But after that when i tried to do inner for hrs_residential_utilities with hrs_utilities, i stopped getting results for hrs_residentials as well. As if we see hrs_residential do have the data inside table. I dont want inner join with hrs_residentials, i want to have inner join between hrs_residential_utilities and hrs_utilities.
Is it possible, or i am following the wrong approach here? Sorry i am not good. What will the Proper Query if anyone can help me with it.
This is the Query i have tried so far.
SELECT R.`ResID`,R.`ResNo`
FROM `hrs_residentials` R
LEFT OUTER JOIN `hrs_residential_utilities` RU
ON R.`ResID` = RU.ResID
INNER JOIN `hrs_utilities` U
ON RU.`UtilityID` = U.`UtilityID`
WHERE 1=1;
I stopped Getting Results from the hrs_residentials table After the Inner Join, but i am making Inner join between other two tables.
Try a subquery like this:
SELECT *
FROM `hrs_residentials` R
LEFT OUTER JOIN
(
SELECT * FROM
`hrs_residential_utilities` RU
INNER JOIN `hrs_utilities` U
ON RU.`UtilityID` = U.`UtilityID`
) AS subqyr
ON R.`ResID` = subqyr.`ResID`
run this query and view the results
SELECT R.ResID,R.ResNo
FROM hrs_residentials R
LEFT OUTER JOIN hrs_residential_utilities RU
ON R.ResID = RU.ResID
then run this query and view the results:
SELECT * FROM hrs_utilities
I suspect what you will find is that the RU.utilities ID does not match anything in the hrs_utilities.
Your query itself should return everything in hrs_residentials and join on any matching data from hrs_residential_utilities this may or may not return RU.ResID as null depending on whether it can match.
It then filters on whether RU.UtilityId matches with anything in the hrs_utilities table, this won't match on null items.
Thanks.
oliver

Difficult to complete a tough query script for me

SELECT a.acikkapali,
b.onay, b.evrakno,
b.tarih,
a.kod,
d.ad,
a.note0,
a.sf_miktar,
a.sf_sf_unit,
a.rtalepedilentestarih,
c.evrakno
FROM stok47T a
LEFT JOIN stok47e b on a.evrakno = b.evrakno
LEFT JOIN stok46t1 c on a.evrakno = c.talepno
LEFT JOIN stok00 d on a.kod = d.kod
WHERE a.tarih = '2013/04/15'
I need to add two my tables into that script with right way that means If I mapped one of them then the normal row count increases this makes me crazy, I have been trying to solve that issue for a couple days but I had been fail many times.
I couldn't find a good mapped fields between stok47t and the others. But there are still a few columns(fields) matches for their types and data.
I need to listen ppl opinions and learns something.
Here is a big part of my query
If you are getting increase in row count then chances are it could be due to using LEFT JOIN. An INNER join might help (see http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html guidance)
SELECT a.acikkapali,
b.onay, b.evrakno,
b.tarih,
a.kod,
d.ad,
a.note0,
a.sf_miktar,
a.sf_sf_unit,
a.rtalepedilentestarih,
c.evrakno
FROM stok47T a
INNER JOIN stok47e b on a.evrakno = b.evrakno
INNER JOIN stok46t1 c on a.evrakno = c.talepno
INNER JOIN stok00 d on a.kod = d.kod
WHERE a.tarih = '2013/04/15'
However without understanding your data structure then there is a chance you might lose the information that you are after.
If you are getting multiple rows, it is probably due to a Cartesian product occurring in the joins. This is unrelated to the type of join (left/right/full/inner). It is based on the relationships between the tables. You have 1-N relationships along different dimensions.
Your conditions are:
FROM stok47T a
LEFT JOIN stok47e b on a.evrakno = b.evrakno
LEFT JOIN stok46t1 c on a.evrakno = c.talepno
LEFT JOIN stok00 d on a.kod = d.kod
I have no idea what these tables and fields mean. But, if you have a case where there is one row per evrakno in table stok47t, and there are two rows in table stok47e and three in table stok46t1, then you will get six rows in the output.
Without more information, it is impossible to tell you the best solution. One method is to summarize the tables. Another is to take the first or last corresponding row, by doing something like:
from stok47T a left join
(select s.*, row_number() over (partition by evrakno order by id desc) as seqnum
from stok47e s
) b
on a.evrakno = b.evrakno and b.seqnum = 1

Getting Repeated values in SQL

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

Optimizing a where statement MYSQL

Im writing this complex query to return a large dataset, which is about 100,000 records. The query runs fine until i add in this OR statement to the WHERE clause:
AND (responses.StrategyFk = strategies.Id Or responses.StrategyFk IS
Null)
Now i understand that by putting the or statement in there it adds a lot of overhead.
Without that statement and just:
AND responses.StrategyFk = strategies.Id
The query runs within 15 seconds, but doesn't return any records that didn't have a fk linking a strategie.
Although i would like these records as well. Is there an easier way to find both records with a simple where statement? I can't just add another AND statement for null records because that will break the previous statement. Kind of unsure of where to go from here.
Heres the lower half of my query.
FROM
responses, subtestinstances, students, schools, items,
strategies, subtests
WHERE
subtestinstances.Id = responses.SubtestInstanceFk
AND subtestinstances.StudentFk = students.Id
AND students.SchoolFk = schools.Id
AND responses.ItemFk = items.Id
AND (responses.StrategyFk = strategies.Id Or responses.StrategyFk IS Null)
AND subtests.Id = subtestinstances.SubtestFk
try:
SELECT ... FROM
responses
JOIN subtestinstances ON subtestinstances.Id = responses.SubtestInstanceFk
JOIN students ON subtestinstances.StudentFk = students.Id
JOIN schools ON students.SchoolFk = schools.Id
JOIN items ON responses.ItemFk = items.Id
JOIN subtests ON subtests.Id = subtestinstances.SubtestFk
LEFT JOIN strategies ON responses.StrategyFk = strategies.Id
That's it. No OR condition is really needed, because that's what a LEFT JOIN does in this case. Anywhere responses.StrategyFk IS NULL will result in no match to the strategies table, and it wil return a row for that.
See this link for a simple explanation of joins: http://www.codinghorror.com/blog/2007/10/a-visual-explanation-of-sql-joins.html
After that, if you're still having performance issues then you can start looking at the EXPLAIN SELECT ... ; output and looking for indexes that may need to be added. Optimizing Queries With Explain -- MySQL Manual
Try using explicit JOINs:
...
FROM responses a
INNER JOIN subtestinstances b
ON b.id = a.subtestinstancefk
INNER JOIN students c
ON c.id = b.studentfk
INNER JOIN schools d
ON d.id = c.schoolfk
INNER JOIN items e
ON e.id = a.itemfk
INNER JOIN subtests f
ON f.id = b.subtestfk
LEFT JOIN strategies g
ON g.id = a.strategyfk