Avoid multiple LEFT JOIN - php

Is there a way to avoid adding a second LEFT JOIN for the table "social_mcouple" to query where social_members.m_id = social_mcouple.c_id below?
$res = #mysql_query("SELECT *, DATE_FORMAT(m_lld,'%m/%d/%y') AS m_lld_formatted FROM social_members
LEFT JOIN social_member_types ON t_id=m_type WHERE m_user='".$en['user']."'");

If there will always be a social_mcouple that corresponds to social_members, or you're only interested in rows where there is a correspondence then you may use an INNER JOIN. If you need all social_members regardless of whether there is a corresponding social_mcouple then you will need a LEFT JOIN. The LEFT JOIN will give you all rows with social_mcouple.* set to NULL where there is not a match.
The performance hit will really depend on the size of your datasets.
EDIT: adding a sample UNION query.
$res = #mysql_query("
(SELECT social_members.*, social_member_types.*, DATE_FORMAT(m_lld,'%m/%d/%y') AS m_lld_formatted,
NULL AS mcouple1, NULL AS mcouple2, NULL AS mcouple3
FROM social_members
LEFT JOIN social_member_types ON t_id=m_type
WHERE m_user='".$en['user']."' AND m_type != 2)
UNION
(SELECT social_members.*, social_member_types.*, DATE_FORMAT(m_lld,'%m/%d/%y') AS m_lld_formatted,
social_mcouple.mcouple1, social_mcouple.mcouple2, social_mcouple.mcouple3
FROM social_members
LEFT JOIN social_member_types ON t_id=m_type
JOIN social_mcouple ON social_members.m_id = social_mcouple.c_id
WHERE m_user='".$en['user']."' AND m_type = 2)
");

Related

Left Join with subquery returns Null

I am applying Left Join with Sub query & where clause
It seems fine no syntax error but the columns I am selecting from that sub query always returns me Null. I have executed the same part in my SQL section, it gives me record. Kindly have a look on the query and let me know if any thing is possible or if question is not clear.
SELECT alt.userId, u.name, t.name AS teamName, alt.startDateTime, v.name AS villageName, c.name AS clusterName, startLat, startLong, latlng.lat, latlng.long
FROM activity_log_tim AS alt
JOIN user AS u ON u.userId = alt.userId
JOIN team_members AS tm ON tm.memberId = u.userId
JOIN team AS t ON t.teamId = tm.teamId
JOIN village AS v ON v.villageId = alt.villageId
JOIN cluster_villages AS cv ON cv.villageId = v.villageId
JOIN cluster AS c ON c.clusterId = cv.clusterId
LEFT JOIN (SELECT lat, long,dateTime, scheduleId FROM activity_log_gps LIMIT 1) AS latlng ON latlng.scheduleId = alt.scheduleId
WHERE DATE(alt.startDateTime) = '2015-09-05' AND DATE(alt.endDateTime) = '0000-00-00' GROUP BY alt.userId ORDER BY latlng.dateTime DESC
Well it's supposed to since you are performing a LEFT JOIN which produces NULL if no match occurs. So either you can perform a INNER JOIN or use a COALESCE function like below
SELECT alt.userId, u.name,
t.name AS teamName,
alt.startDateTime,
v.name AS
villageName,
c.name AS clusterName,
startLat,
startLong,
COALESCE(latlng.lat, 23), //Notice the use of COALESCE. If null will return 23 as default
COALESCE(latlng.long, 32)

join and null values rows not showing

I have this statement:
SELECT personen.*, klassen.naam as klas FROM `personen`
JOIN `klassen` ON `klassen`.id = `personen`.Id
WHERE `rol` = "Docent" ORDER BY id
I know that it basically puts the column klassen.naam into personen by checking if the foreign key K_Id is the same as the id of Klassen:
In the table above I have 4 results, these are all the people who have a K_Id assigned, however there are 2 more people who have a K_Id of null:
My problem is that when K_Id is null it doesn't return anything at all, which makes sense, I just don't know how to fix it.
My question is: How can i write the statement so that it still shows all the other rows where the K_Id value is null?
SELECT personen.*, klassen.naam as klas
FROM `personen`
JOIN `klassen`
ON `klassen`.id = `personen`.Id
WHERE `rol` = "Docent"
ORDER BY id
You should use left join if you want all of your data from personen Table where personen.id is not present in klassen table it look like this
SELECT personen.*, klassen.naam as klas
FROM `personen`
LEFT JOIN `klassen`
ON `klassen`.id = `personen`.Id
WHERE `rol` = "Docent"
ORDER BY id
You would use a left join for this purpose. Assuming rol is in the personen table:
SELECT p.*, k.naam as klas
FROM `personen` p LEFT JOIN
`klassen` i
ON i.id = p.Id
WHERE p.`rol` = 'Docent'
ORDER BY p.id;
If rol is in the klassen table, then:
SELECT p.*, k.naam as klas
FROM `personen` p LEFT JOIN
`klassen` i
ON i.id = p.Id AND i.`rol` = 'Docent'
ORDER BY p.id;
Note that I also introduced table aliases in the query. These make queries easier to write and to read.
Also, this will return all rows in the personen table (subject to the where), including non-matches. If you just specifically wanted NULL values, then you would use:
SELECT p.*, k.naam as klas
FROM `personen` p JOIN
`klassen` i
ON i.id = p.Id or p.id is null
WHERE p.`rol` = 'Docent'
ORDER BY p.id;
I'm guessing you really want the left join version.

Add a filter to a large mysql query

I have this large query, and I just need to filter out any results where the tbl_dealinterest.Active = 'n'. There sometimes isn't an entry in that table for the product, and sometimes it might there might be and entry and set to y.
Here is the large ugly query:
SELECT tbl_product.id, tbl_productspecification.id AS specificationId,
tbl_product.ProductId, tbl_seller.CompanyName, tbl_product.ProductName, tbl_product.Description, mst_Categories.id AS 'Category',
tbl_productspecification.RetailPrice, tbl_productspecification.SalePrice,
tbl_product.image, tbl_productspecification.Discount, tbl_product.EndTime, tbl_product.Seller_Id, tbl_dealinterest.Active AS thumbsActive
FROM tbl_product
LEFT OUTER JOIN tbl_seller ON tbl_seller.SelId = tbl_product.Seller_Id
LEFT OUTER JOIN mst_Categories ON (mst_Categories.id = tbl_product.Category OR mst_Categories.id = tbl_product.SubCategory)
LEFT OUTER JOIN tbl_productspecification ON tbl_productspecification.ProductId = tbl_product.ProductId
LEFT OUTER JOIN mst_image ON mst_image.Product = tbl_product.ProductId
LEFT OUTER JOIN tbl_dealinterest ON tbl_dealinterest.ProductId = tbl_product.ProductId AND tbl_dealinterest.BuyerId = '$token'
WHERE tbl_product.Active='y'
AND tbl_product.StartTime <= '".date("Y-m-d H:i:s")."'
AND tbl_product.EndTime > '".date("Y-m-d")." 06:00:00'
".$subquery."
GROUP BY tbl_productspecification.ProductId";
Thanks for any suggestions.
SELECT ...
WHERE tbl_product.Active='y'
AND (tbl_dealinterest.Active <> 'n' OR tbl_dealinterest.Active IS NULL)
...
LEFT OUTER JOIN tbl_dealinterest ON (tbl_dealinterest.ProductId = tbl_product.ProductId
AND tbl_dealinterest.BuyerId = '$token'
AND tbl_dealinterest.Active<>'n')

PHP/MYSQL Query if not in second table

I have two tables. I want to draw a sample of the first table except where the person in the first table is also in a second table. Am having trouble doing this seemingly simple query.
table users
id|name
table catuser
id|userid|catid
I have tried
SELECT u.*,c.userid FROM `users` u
LEFT JOIN `catuser` c
ON (u.id = c.userid AND c.userid <> '197')
WHERE u.id = '1'
and variations to no avail. Would appreciate any suggestions.
How abt. this:
SELECT u.*,c.userid
FROM `users` u
LEFT JOIN `catuser` c
ON u.id = c.userid
WHERE u.id = '1'
AND c.userid <> '197'
AND c.userid is null
SELECT * FROM users WHERE id NOT IN (SELECT DISTINCT userid FROM catuser)
If you want to query only users that have one or more categories, you can use a WHERE EXISTS query:
SELECT u.* FROM `users` u
WHERE EXISTS (SELECT * FROM catuser WHERE catuser.userid = u.id)
Another possibility is to do a left join, and check whether the join succeeded on checking on null:
SELECT u.*, c.* FROM `users` u
LEFT JOIN catuser c ON u.id = c.userid
WHERE c.id IS NOT NULL
If there is no corresponding row in catuser, all catuser fields will be null. By checking whether c.id is not null, you only include the rows with a category.
Note that the join may return a user multiple time, if he is in multiple categories.

Getting the maximum value from interrelated MySQL tables

I am trying to unify a pair of queries with a LEFT JOIN, so that I can perform an ORDER BY on a desired column.
Table A has an exclusive one-to-many relationship with Table B, and table B has an exclusive one-to-many relationship with Table C.
I want to get the maximum value of a column in Table C, for each row in Table A.
what I used to have was:
$tableA = SELECT * FROM tableA;
for each row in $tableA {
$maxValue = SELECT MAX(value) FROM tableC WHERE tableB_id IN (SELECT tableB_id FROM tableB WHERE tableA_id={$row['tableA_id']}) GROUP BY tableB_id;
}
and now I'm thinking along the lines of:
SELECT * FROM tableA LEFT JOIN (SELECT tableA_id, MAX(max_c_value) FROM (SELECT tableB_id, MAX(value) max_c_value FROM tableC GROUP BY tableB_id) t GROUP BY tableA_id) USING(tableA_id)
but I know that's gibberish. I am not sure where to go from here.
I'm finding it hard to explain the problem, sorry.
SELECT A.ID, MAX(C.MyField) as CField
FROM A
LEFT OUTER JOIN B
ON A.ID = B.A_ID
LEFT OUTER JOIN C
ON B.ID = C.B_ID
GROUP BY A.ID
You will get null value for CField if there is no rows corresponding.
select max(table3.field),table1.field from table1
join table2 on table1.id=table2.table1_id
join table3 on table2.id = table3.table2_id
group by table1.field
You were closer on the first try I think. You want something like this:
SELECT MAX(tableC.cValue) FROM tableA
LEFT JOIN tableB
ON tableA.tableA_id = tableB.tableA_id
LEFT JOIN tableC
ON tableB.tableB_id = tableC.tableB_id
http://www.w3schools.com/sql/sql_join.asp
I have managed to solve it on my own, only to come back here and find I was making things far too complicated for myself, getting lost in a sea of tables!
This code did actually work, but I have already replaced it with the simpler code suggested above:
SELECT * FROM A LEFT JOIN (
SELECT A_ID, MAX(val) FROM (
SELECT * FROM B LEFT JOIN (
SELECT B_ID, MAX(val) val FROM C GROUP BY B_ID
) x USING(B_ID)
) y GROUP BY A_ID
) z USING(A_ID);

Categories