mysql选择一个表中的所有行,即使其他使用中间表不匹配

时间:2015-04-15 22:39:05

标签: mysql join

我无法从表格中选择所有行并使用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

如果我运行用户名" vedran"的查询我想得到像这样的输出

------------------------------------------------------------------
| id    | menu_name     | modul_name    | all_access    | active |
------------------------------------------------------------------
 1          books           book            0               1
 2          cds             cd              0               1
 3          tapes           tape            0               0

因此用户vedran的id为1,id为1的用户有活动的模块1和2,但我也想获得第三个模块,但设置为0。

模型看起来像这样: model

我尝试使用此查询:

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

但这只返回两行而不是" modul"的所有行。表

3 个答案:

答案 0 :(得分:2)

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'

编辑1 CROSS JOIN经典解决方案,没有棘手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';

答案 1 :(得分:0)

也许您可以使用UNIONNOT IN执行此类操作:

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"

基本上,我正在做的事情,在获取用户可以访问的所有模块,并在1列中添加active的值,然后,我添加到此列出用户无法访问的所有模块,其值为0

也许这段代码包含一些错误,因为我没有尝试过(我没有数据库来测试它),但我认为你得到了它。

我希望我帮助你完成你的项目。

编辑:也许您可以使用temporary table来避免重复查询

答案 2 :(得分:0)

如果您想要modul表中的所有行,我的建议是先放置该表,然后将left join用于其余表:

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

WHERE逻辑移到ON子句非常重要。

我不建议在同一查询中混合使用left joinright join。关于哪个表保留所有行,会让人感到困惑。