我正在尝试编写一个MySQL查询,该查询将连续三个表连接到主表,但这有条件地基于最后一个表的连接值。我试图做的两种方式都有问题:
表结构是现有系统的一部分,我无法更改它。一旦我弄清楚SQL,我将不得不找到一种方法将它与它的查询系统集成,所以SQL越简单越好!
我将在这里提出很多细节,对不起,这是一篇很长的帖子,但我认为最好包含所有信息。
以下是更多信息:
数据模型:
存在用户,课程和中间内容类型,其存储特定课程上的每个用户的用户信息,称为cui。 我需要查看所有用户的列表,如果有该用户和课程的cui,也要包含它。
在数据库中,cui的字段内容存储在单独的表中,并通过cui_id连接,这是麻烦的一部分。
剥离数据库结构:
加入
user user_field node course_field
---- ---------- ------- ------------
uid ==== uid
name cui_id =========== cui_id ===== cui_id
course_id = 202
尝试查询:
以下查询在具有以下用户的小样本数据集上运行:
第一个查询是最后一个表上的条件连接,问题是它包含一个额外的行,用户2不是正确的cui。 我不想要GROUP BY,因为我认为它不一定会给我正确的行。
SELECT user.uid, user.name, field_user.cui_id,
field_course.course_id
FROM user
LEFT JOIN field_user
ON
user.uid = field_user.uid
LEFT JOIN node AS cui
ON
cui.id = field_user.cui_id
LEFT JOIN field_course
ON
field_course.cui_id = cui.id
AND
field_course.course_id = 202
结果:
uid name cui_id course_id
---------------------------------------------
4 User One 772 NULL
5 User Two 434 202
5 User Two 771 NULL
35 User Six NULL NULL
另一种选择是:
SELECT user.uid, user.name, field_user.cui_id,
field_course.course_id
FROM user
LEFT JOIN field_user
ON
user.uid = field_user.uid
LEFT JOIN node AS cui
ON
cui.id = field_user.cui_id
LEFT JOIN field_course
ON
field_course.cui_id = cui.id
WHERE (
field_course.course_id = 202 OR ISNULL(field_course.course_id))
结果:
uid name cui_nid course_nid
---------------------------------------------
5 User Two 434 202
35 User Six NULL NULL
麻烦的是它遗漏了用户一,因为用户一确实有其他的美食,只是没有正确的课程。
所以问题是,我该如何得到这个?
uid name cui_id course_id
--------------------------------------------
4 User One 772 NULL
5 User Two 434 202
35 User Six NULL NULL
答案 0 :(得分:1)
真的不是那么漂亮但是应该这样做:
-- Select to get all users irrespective of whether they have a row in field_course or field_user
SELECT user.uid, user.name, field_user.cui_id,
null as course_id
FROM user
LEFT JOIN field_user ON user.uid = field_user.uid
LEFT JOIN node AS cui ON cui.id = field_user.cui_id
where user.uid not in
(
-- Inline view to get only users that have both a field_course & field_user row
SELECT user.uid
FROM user
INNER JOIN field_user ON user.uid = field_user.uid
INNER JOIN node AS cui ON cui.id = field_user.cui_id
INNER JOIN field_course ON field_course.cui_id = cui.id
where field_course.course_id = 202
)
union all
-- Select to get only users that have both a field_course & field_user row
SELECT user.uid, user.name, field_user.cui_id,
field_course.course_id
FROM user
INNER JOIN field_user ON user.uid = field_user.uid
INNER JOIN node AS cui ON cui.id = field_user.cui_id
INNER JOIN field_course ON field_course.cui_id = cui.id
where field_course.course_id = 202;
修改强>
以下是我用来测试的表结构和数据:
CREATE TABLE `user` (
`uid` int(10) unsigned NOT NULL,
`name` varchar(20) NOT NULL
);
CREATE TABLE `node` (
`id` int(10) unsigned not null primary key
);
CREATE TABLE `field_user` (
`uid` int(10) unsigned NOT NULL,
`cui_id` int(10) unsigned NOT NULL
);
CREATE TABLE `field_course` (
`uid` int(10) unsigned NOT NULL,
`cui_id` int(10) unsigned NOT NULL,
`course_id` int(10) unsigned NOT NULL
);
insert into user (uid,name) values (4,"User One");
insert into user (uid,name) values (5,"User Two");
insert into user (uid,name) values (35,"User Six");
insert into node (id) values (771);
insert into node (id) values (772);
insert into node (id) values (434);
insert into field_user (uid,cui_id) values (4,772);
insert into field_user (uid,cui_id) values (5,434);
insert into field_user (uid,cui_id) values (5,771);
insert into field_course (uid,cui_id,course_id) values (5,434,202);