繁体   English   中英

MySQL从一个表中选择所有行,即使使用中间表在其他表中不匹配

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

我在从表中选择所有行并用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。

模型看起来像这样: 模型

我尝试使用此查询:

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”表中的所有行。

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';

也许您可以使用UNION来执行此操作,而NOT 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"

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

也许这段代码包含一些错误,因为我没有尝试过(我没有数据库可以对其进行测试),但是我想您已经明白了。

希望对您的项目有所帮助。

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

如果要从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联接。 关于哪个表保留其所有行,这令人感到困惑。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM