There are some similar questions, but none of them matches my case.
SQL Optimization - Join different tables based on column value
How to JOIN on different tables based on column value
MySQL query to JOIN tables based on column values
MySQL: Use CASE/ELSE value as join parameter
MySQL query where JOIN depends on CASE
I have notifications table with this structure
CREATE TABLE `notifications` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`notificaiton_type_id` int(11) DEFAULT NULL,
`table1_id` int(11) DEFAULT NULL,
`table2_id` int(11) DEFAULT NULL,
`table3_id` int(11) DEFAULT NULL,
`table4_id` int(11) DEFAULT NULL,
`table5_id` int(11) DEFAULT NULL,
`user_id` int(11) DEFAULT NULL,
`created` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `userIdIndex` (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
and 5 tables, from table1 to table5, with these structure (others are the same: I set this for testing, not sure if it matters, but those tables (1 to 5) in addition to posted fields have other fields as well, just they do not participate in the query, so for simplicity I just skipped them)
CREATE TABLE `table1` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(300) COLLATE utf8_bin DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=34 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
table*_id is foreign key for tables: table1 - table5 with one to many relationship.
I should select notifications based on user_id
. Based on notification type, appropriate table*_id has some value, other foreign_keys are null(btw there are notification types that 2 or even 3 table *_id
's can be different from null ). The initial thought was to have a query that would join only those tables, if the foreign key has some value different from null via using CASE, WHEN, but as I learnt from the answer of this question,
MySQL query where JOIN depends on CASE
it can not be used in this case.
Tables table1-table5 are going to be relatively big, having kinda millions or dozens of millions records. So I would not prefer to join extra 2-4 tables if foreign keys are null. Also, I do not think it is any better to separate the query into 2 main parts, like - first getting the notifications and then in a loop find associated tables' values.
So, the point is to only join those tables that table*_id
is not null if it can be done in mysql.
The main question is what would be the most efficient way to achieve this - get notification info with its related tables data.
general query with joins to all tables is a usual left join, smth like this
EXPLAIN SELECT
n.`id`,
n.`user_id`,
n.`table1_id`,
n.`table2_id`,
n.`table3_id`,
n.`table4_id`,
n.`table5_id`
// other fields
FROM
notifications AS n
LEFT JOIN table1 AS t1
ON t1.`id` = n.`table1_id`
LEFT JOIN table2 AS t2
ON t2.`id` = n.`table2_id`
LEFT JOIN table3 AS t3
ON t3.`id` = n.`table3_id`
LEFT JOIN table4 AS t4
ON t4.`id` = n.`table4_id`
LEFT JOIN table5 AS t5
ON t5.`id` = n.`table5_id`
WHERE user_id = 5
here is sql fiddle with data http://sqlfiddle.com/#!2/3bf8f/1/0
Thanks