I have a table called notifications
:
CREATE TABLE `notifications` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `user_id` int(11) DEFAULT NULL, `type` varchar(20) NOT NULL DEFAULT '', `parent_id` int(11) DEFAULT NULL, `parent_type` varchar(15) DEFAULT NULL, `type_id` int(11) DEFAULT NULL, `etc` NULL PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=25 DEFAULT CHARSET=utf8;
Each notification
is related to a different table, the value of parent_type
field specifies the name of the table that I want to * join
the table with. All target tables have several similar columns:
CREATE TABLE `tablename` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `is_visible` tinyint(1) NOT NULL, `etc` NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
Currently I'm using this query for selecting notifcations that their related row in the target table exists and their is_visible
field is 1
:
SELECT n.id, FROM notifications n LEFT JOIN books b ON n.parent_id = b.id AND n.parent_type = 'book' AND b.is_visible = 1 LEFT JOIN interviews i ON n.parent_id = i.id AND n.parent_type = 'interview' AND i.is_visible = 1 LEFT JOIN other tables... WHERE n.user_id = 1 GROUP BY n.id
But since it is a LEFT JOIN
it returns the notification if it matches any table or not, how can I rewrite it so it doesn't return notifications that don't match with any row in the target table? I have also tried the CASE
statement unsuccessfully.
To join two tables based on a column match without loosing any of the data from the left table, you would use a LEFT OUTER JOIN. Left outer joins are used when you want to get all the values from one table but only the records that match the left table from the right table.
Merging tables by columns. Multiple tables can be merged by columns in SQL using joins. Joins merge two tables based on the specified columns (generally, the primary key of one table and a foreign key of the other).
There are four main types of JOINs in SQL: INNER JOIN, OUTER JOIN, CROSS JOIN, and SELF JOIN.
I'm not 100% sure the syntax is right and I have no chance to test it right now, but the idea should be clear.
SELECT DISTINCT n.id FROM notifications n JOIN ( (SELECT b.id, 'book' AS type FROM books b WHERE b.is_visible = 1) UNION (SELECT i.id, 'interview' AS type FROM interviews i WHERE i.is_visible = 1) ) ids ON n.parent_id = ids.id AND n.parent_type = ids.type WHERE n.user_id = 1
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With