The below example shows how to return the difference in tables from a MySQL query
Problem: A user has the ability to assign labels to records. When a user is to add a new label to a record only query the labels the user has access to and don't display the labels already assigned.
//selects all available labels to user '1' SELECT labels.label_id, labels.label FROM labels LEFT JOIN labels_users USING (label_id) WHERE (labels.entry_user = '1' || labels_users.user_id = '1') //returns // label_id: 1, label: Test Label // label_id: 2, label: Testing Number 2 // label_id: 3, label: Third Label
//selects currently assigned labels to record SELECT labels.label_id, labels.label FROM labels LEFT JOIN labels_records USING (label_id) WHERE labels_records.record_id = '99' //returns // label_id: 1, label: Test Label // label_id: 3, label: Third Label
Solution: Use SELECT DISTINCT to limit our results from two subqueries.
SELECT DISTINCT availableLabels.label_id, availableLabels.label
FROM (
SELECT
labels.label_id, labels.label
FROM labels
LEFT JOIN labels_users USING (label_id)
WHERE (labels.entry_user = '1' || labels_users.user_id = '1')
) AS availableLabels
LEFT JOIN (
SELECT
labels.label_id
FROM labels
LEFT JOIN labels_records USING (label_id)
WHERE labels_records.record_id = '99'
) AS assignedLabels ON availableLabels.label_id = assignedLabels.label_id
WHERE assignedLabels.label_id IS NULL
ORDER BY availableLabels.label ASC
//returns
// label_id: 2, label: Testing Number 2The reason we use "WHERE assignedLabels.label_id IS NULL" is because when we "LEFT JOIN" our assignedLabels to the availableLabels, we want the results that are not being used.
