问题
I am having trouble with selecting all rows from a table and populating non matching ones with 0.
Table "modul" ---------------------------------------------------------- | id | menu_name | modul_name | all_access | ---------------------------------------------------------- 1 books book 0 2 cds cd 0 3 tapes tape 0
table "user" -------------------- | id | username | -------------------- 1 vedran
table "user_modul" ------------------------------------------ | id | user_id | modul_id | active | ------------------------------------------ 1 1 1 1 2 1 2 1 3 2 2 1
If I run the query for username "vedran" I'd like to get an output like this
------------------------------------------------------------------ | id | menu_name | modul_name | all_access | active | ------------------------------------------------------------------ 1 books book 0 1 2 cds cd 0 1 3 tapes tape 0 0
So user vedran has id 1 and user with id 1 has active modules 1 and 2 but I'd like to get third module as well but set to 0.
Model looks like this:
I tried using this query:
SELECT M.*, ZM.active FROM modul M JOIN user_modul UM ON (M.id = UM.modul_id) JOIN user U ON (UM.user_id = U.id) WHERE U.id = 1 ORDER BY M.id ASC
But that returns just the two rows and not all the rows from "modul" table.
回答1:
http://sqlfiddle.com/#!2/30f01/1
SELECT
m.* , COALESCE(um.active,0)
FROM user u
RIGHT JOIN modul m
ON 1
LEFT JOIN user_modul um
ON um.modul_id = m.id AND um.user_id=u.id
WHERE u.username='vedran'
EDIT 1 CROSS JOIN classic solution without tricky ON 1
http://sqlfiddle.com/#!2/30f01/2
SELECT
m.* , COALESCE(um.active,0)
FROM user u
CROSS JOIN modul m
LEFT JOIN user_modul um
ON um.modul_id = m.id AND um.user_id=u.id
WHERE u.username='vedran';
回答2:
Maybe you can do this with UNION
and NOT IN
with something like that :
SELECT modul.id AS id, modul.menu_name AS menu_name, modul.modul_name AS modul_name, modul.all_access AS all_access, "1" AS active
FROM modul
LEFT JOIN user_modul
ON user_modul.modul_id = modul.id
LEFT JOIN user
ON user.id = user_modul.user_id
WHERE user.username = "vedran"
UNION
SELECT id, menu_name, modul_name, all_access, "0" AS active
FROM modul
WHERE id NOT IN
SELECT modul.id
FROM modul
LEFT JOIN user_modul
ON user_modul.modul_id = modul.id
LEFT JOIN user
ON user.id = user_modul.user_id
WHERE user.username = "vedran"
Basicaly, What I'm doing with this, in getting all the moduls the user can access, and adding a value of 1
in the column active
, then, I add to this table all the moduls the user can't access, with a value of 0
.
Maybe this code contains some errors, because I havn't tried it (I don't have the database to test it), but I think you got it.
I hope I helped you in your project.
EDIT : Maybe you can use a temporary table
to avoid duplicating the query
回答3:
If you want all rows from the modul
table, my recommendation is to put that table first and then use left join
for the rest of the tables:
SELECT M.*, COALESCE(UM.active, 0)
FROM modul M LEFT JOIN
user_modul UM
ON M.id = UM.modul_id LEFT JOIN
user U
ON UM.user_id = U.id AND U.id = 1
ORDER BY M.id ASC
It is important to move the WHERE
logic to an ON
clause.
I don't recommend mixing left join
and right join
in the same query. It gets confusing as to which table keeps all its rows.
来源:https://stackoverflow.com/questions/29662159/mysql-selecting-all-rows-from-one-table-even-if-no-match-in-other-using-middle-t