mysql selecting all rows from one table even if no match in other using middle table

爷,独闯天下 提交于 2021-02-15 07:47:02

问题


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: model

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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!