JOIN SQL is not working when join table is empty - mysql

I am working on a project where multiple table data exists for a user but if empty one table from any of them then SQL return empty data even other tables data exist like below SQL
$id = 40;
SELECT *
FROM players a
JOIN pitcher b
ON a.id = b.user_id
JOIN outfield_position c
ON a.id = c.user_id
JOIN infield_position d
ON a.id = d.user_id
JOIN defensive_statistics e
ON a.id = e.user_id
JOIN career f
ON a.id = f.user_id
WHERE a.id = $id
like if $outfield_position table is empty then the SQL returns an empty array but sometimes maybe data here, what can I do if data available or not available every way can works?
Thanks

The default join used is inner join and as already explained here joins .
The output in this case will be intersection of the tables it is joined with,so if any table does not have any value then intersection will give empty result.
You can try with LEFT OUTER JOIN or FULL OUTER JOIN , in Left Outer Join if data is present in $players the value will be displayed.If unsure about the data Full Outer join will give all the results from all the tables.

Related

Using column as table join with concat

I've been trying to join another table with the table name matching a value in a column from another table.
If I hard-code the table name to a matching table like __gun it works fine but I cannot get the col value to be used + concat underscores to the beginning.
The problem lies in the left join here:
left join CONCAT('__', b.related_table) c on b.related_id = c.id
I need the related_table column to be used in the join. With __ before it.
Attempts:
SELECT a.*, c.*, b.equipable, b.related_table FROM inventory a
inner join items b on a.item_id = b.id
left join CONCAT('__', b.related_table) c on b.related_id = c.id
WHERE 1=1
and a.id = :inventory_id
and a.user_id = :user_id
SELECT a.*, c.*, b.equipable, b.related_table FROM inventory a
inner join items b on a.item_id = b.id
left join '__'+b.related_table c on b.related_id = c.id
WHERE 1=1
and a.id = :inventory_id
and a.user_id = :user_id
SELECT a.*, c.*, b.equipable, b.related_table FROM inventory a
inner join items b on a.item_id = b.id
left join "__"+Cast(b.related_table as nvarchar(4000)) c on b.related_id = c.id
WHERE 1=1
and a.id = :inventory_id
and a.user_id = :user_id
Thank you for considering my question
You cannot construct a table name.
Plan A: Rethink the schema. It is usually bad design to have multiple 'identical' tables.
Plan B: Write a Stored Procedure that uses CONCAT, PREPARE, EXECUTE, and DEALLOCATE_PREPARE to build and run the query.
You can do this using Prepared Statements or you can say dynamic SQL. Follow these steps :
Use SET for table name.
Use CONCAT to get the desired table name.
PREPARE statement for table created at step 1.
EXECUTE statement.
DEALLOCATE PREPARE to release the prepared statement.

MySql return empty result when one of table for JOIN is not any data

with below Sql query i can get result successful when all of tables has data, but in this my query when transactions table has not any saved data and its empty my query return empty result, but i want to get null or empty columns data
SELECT transactions.id,
userEwallets.ewalletNumber,
userEwallets.currencySymbol,
transactions.money,
transactions.transactionType,
b.username AS toUser,
a.username AS sender
FROM transactions
JOIN userEwallets ON transactions.ewalletId = userEwallets.id
LEFT JOIN users AS b ON b.id = transactions.toUserId
LEFT JOIN users AS a ON a.id = transactions.fromUserId
WHERE transactions.userId = 37
when its not empty i get this result:
id ewalletNumber currencySymbol money transactionType toUser sender
95 SHIRR9373036569 IRR 20 1 1 amin
you can use a dummy table with one row. The other tables should be left joined to it.
SELECT transactions.id,
userEwallets.ewalletNumber,
userEwallets.currencySymbol,
transactions.money,
transactions.transactionType,
b.username AS toUser,
a.username AS sender
FROM (select 1) dummy
LEFT JOIN transactions ON transactions.userId = 37
LEFT JOIN userEwallets ON transactions.ewalletId = userEwallets.id
LEFT JOIN users AS b ON b.id = transactions.toUserId
LEFT JOIN users AS a ON a.id = transactions.fromUserId
You can allways use a subquery instead of a table name if you give it an allias. Note that you have to move the WHERE condition for the left joined table into the ON clause - Othewise MySQL will convert it to an INNER JOIN.
You are using where condition here. where transactions.userId = 37. If there is no data in transactions table, that where condition will fail and hence returns no data
In order to accomplish that, you should use another table to be the first one. The way you are doing it, if there are no records in the transactions table then there would be nothing to join with.
So, use a table that always has records and LEFT JOIN it with the others.
Try this:
SELECT transactions.id,
userEwallets.ewalletNumber,
userEwallets.currencySymbol,
transactions.money,
transactions.transactionType,
b.username AS toUser,
a.username AS sender
FROM users AS b
LEFT JOIN transactions ON b.id = transactions.toUserId
LEFT JOIN users AS a ON a.id = transactions.fromUserId
JOIN userEwallets ON transactions.ewalletId = userEwallets.id
WHERE transactions.userId = 37

Cartesian join with multple outer joins to common root

I have the following schema.
I can run two queries fairly simply
select * from booking_model_assignment
join booking_model on booking_model_assignment.booking_model_id = booking_model.id
left outer join axis_channel_mappings on bmi_id = axis_channel_mappings.assignment_id
left outer join axis_revenue_stream_mappings on bmi_id = axis_revenue_stream_mappings.assignment_id
which will give me all of the combinations of channel mappings and 'revenue_stream_mappings' which fit a booking model, with Null if there is one which only matches in one of the tables.
The other query
select * from axis_channel join axis_revenue_stream
Gives all of the possible combinations of channels and revenue streams.
What I would like is a query which will give all of the combinations, and the booking_model if that combination matches.
Any time I try to join or subquery I seem to get too many, or too few results. I think the issue is that I want the assignment_id to match across outer joins but only if there is an outer join.
The schema is laid out like this so it will be possible to add new axis and fit models to combinations, so if there is an easier way to achieve this I would be open to changing the schema.
EDIT
I have a partial solution based on Eggyal's answer but it is not extendable.
SELECT c.*, r.*, GROUP_CONCAT(a.bmi_id), GROUP_CONCAT(b.name) AS booking_models
FROM axis_channel c
CROSS JOIN axis_revenue_stream r
LEFT JOIN axis_channel_mappings cm ON cm.channel_id = c.id
LEFT JOIN axis_revenue_stream_mappings rm ON rm.revenue_stream_id = r.id
LEFT JOIN booking_model_assignment a ON (a.bmi_id = cm.assignment_id
AND a.bmi_id = rm.assignment_id)
OR (a.bmi_id = cm.assignment_id
AND rm.assignment_id IS NULL)
OR (cm.assignment_id IS NULL
AND a.bmi_id = cm.assignment_id)
LEFT JOIN booking_model b ON b.id = a.booking_model_id
GROUP BY c.id, r.id
But if I were to add more axes this query would grow way to cumbersome.
SELECT c.*, r.*, GROUP_CONCAT(b.name) AS booking_models
FROM axis_channel c
CROSS JOIN axis_revenue_stream r
LEFT JOIN axis_channel_mappings cm ON cm.channel_id = c.id
LEFT JOIN axis_revenue_stream_mappings rm ON rm.revenue_stream_id = r.id
LEFT JOIN booking_model_assignment a ON a.bmi_id = cm.assignment_id
AND a.bmi_id = rm.assignment_id
LEFT JOIN booking_model b ON b.id = a.booking_model_id
GROUP BY c.id, r.id

Join MySQL tables based on condition?

Problem:
I'm trying to figure out how to join tables based on a condition in an SQL statement. I've spent an hour searching Google, SO, various websites and the MYSQL manual, but I just can't find the correct syntax for what I want to do.
I can't post the exact query I'm trying to get working, but I will post a simplified version for simplicity reasons.
Scenario:
Assuming I have three tables, a = person table, b = address table and c = car table.
Table b will always be joined to table a, becuase a person always lives at an address, but table c should only be joined to a if the value in the 'car_id' field is more than 0, because having a car is optional.
The query:
SELECT a.firstname, a.lastname, a.gender, a.address_id, b.address_firstline, b_address_secondline, b.postcode, c.car_manufacturer, c.car_model
FROM a
INNER JOIN b ON b.id = a.address_id
INNER JOIN c ON c.id = a.car_id AND a.car_id > 0
WHERE a.id = 1
The query above will run fine for a person with the id of 1 because he owns a car. However, if the query is run for a person with the id of 2, the query will return 0 rows because she does not own a car.
How do I make this second JOIN optional? I've tried using the IF ELSE statement, but I'm forever getting syntax errors. Could someone point me in the right direction here? Thanks in advance
You should use left outer join to join c with a.
SELECT a.firstname, a.lastname, a.gender, a.address_id, b.address_firstline, b_address_secondline, b.postcode, c.car_manufacturer, c.car_model
FROM a
INNER JOIN b ON b.id = a.address_id
LEFT OUTER JOIN c ON c.id = a.car_id AND a.car_id > 0
WHERE a.id = 1
Use LEFT JOIN instead of INNER JOIN on table c.
Unilateral joins work on this scenario.
A brief explanation.
a INNER JOIN b ON a.field1 = b.field1 returns every row for which both a.field1 and b.field1 exist and are equal
a LEFT JOIN b ON a.field1 = b.field1 returns every row from table a and returns every row in table b for which a.field1 = b.field1, and null values for non-matching values on table b.
RIGHT JOIN is analogous to LEFT JOIN

Check id joining 3 tables

I have a MySQL JOIN query where 2 tables are joined to get the output
select distinct (a.error_type),a.links_id, a.crawl_cycle , b.* from $table a inner join crawler_error_type b on a.error_type = b.error_type where a.projects_id = '$pid' and b.error_priority_page_level='High'
Now I want to check if the value of the field error_type is present in the third table. If it is present then it shouldn't give me the resulted row.
Add the below:
LEFT OUTER JOIN third_table c ON c.error_type = a.error_type
and
WHERE c.error_type is null
LEFT OUTER JOIN will display all the records from a table joining on third_table. Since you do not want the record with matching error type from third_table, use WHERE c.error_type is null
You need to add one more INNER JOIN on third_table as:
SELECT DISTINCT a.error_type, a.links_id, a.crawl_cycle , b.*
FROM $table a
INNER JOIN crawler_error_type b
ON a.error_type = b.error_type
INNER JOIN third_table c
ON a.error_type = c.error_type
WHERE a.projects_id = '$pid' AND
b.error_priority_page_level='High'.
If I understand it correctly, you should just be able to inner join the third table. Inner joins will on show the record if they have records in the joining tables. If I am misunderstanding could you please elaborate. Thx
select distinct (a.error_type),a.links_id, a.crawl_cycle , b.*
from $table a
inner join crawler_error_type b on a.error_type = b.error_type
inner join some_table_3 c on c.error_type = a.error_type
where a.projects_id = '$pid' and b.error_priority_page_level='High'