[英]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 join
和right join
联接。 关于哪个表保留其所有行,这令人感到困惑。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.