我有3张桌子:
ONE (ID - TYPE)
TWO (ID - FIELDa)
THREE (ID - FIELDb)
如果ONE.TYPE = 0
我将ONE
与TWO
加入,否则如果ONE.TYPE = 1
加入THREE
。
如何使用所有记录执行单个连接选择查询?
结果:
TYPE - RESULT (FIELDa or FIELDb)
我写这个:
SELECT `m`.`meal_name`,
`m`.`short`,
`m`.`id`,
`m`.`time`,
`m`.`budget`,
`p`.`filename`,
`t`.`type`,
CASE `m`.`author_type`
WHEN 0 THEN `a`.`author`
WHEN 1 THEN `u`.`first_name`
ELSE NULL
END AS autore
FROM
`photos` p,
`types` t,
`meals` m
LEFT JOIN `authors` a
ON `m`.`author_type`=0 AND (`m`.`id` = `a`.`id` )
LEFT JOIN `users` u
ON `m`.`author_type`=1 AND (`m`.`id` = `u`.`user_id` )
WHERE
`m`.`type` = `t`.`id`
AND
`m`.`id` = `p`.`id`
但它只返回了一些记录,其中author_type = 0 ....任何想法?
谢谢。
答案 0 :(得分:1)
您可以在每个LEFT JOIN
中使用ONE.TYPE
的相应条件执行两个SELECT
,并在最终COALESCE()
列表中使用LEFT JOIN
在非空值之间进行选择SELECT
ONE.ID,
TYPE,
/* The LEFT JOINs will return NULL for one of these.
Use COALESCE() to get the non-null result
If neither matches, NULL is returned
*/
COALESCE(TWO.Fielda, THREE.FIELDb) AS RESULT
FROM
ONE
LEFT JOIN TWO ON (ONE.TYPE = 0 AND ONE.ID = TWO.ID)
LEFT JOIN THREE ON (ONE.TYPE = 1 AND ONE.ID = THREE.ID)
返回的值:
FROM
您不应该将隐式连接与显式连接混合使用,实际上您根本不应该使用旧式隐式连接(LEFT JOIN
子句中的逗号分隔表)。将它们转换为显式SELECT `m`.`meal_name`,
`m`.`short`,
`m`.`id`,
`m`.`time`,
`m`.`budget`,
`p`.`filename`,
`t`.`type`,
COALESCE(a.author, u.firstname) AS autore
FROM
/* Replace all the implicit joins */
meals m
LEFT JOIN photos p ON m.id = p.id
LEFT JOIN type t ON m.t
LEFT JOIN `authors` a
ON `m`.`author_type`=0 AND (`m`.`id` = `a`.`id` )
LEFT JOIN `users` u
ON `m`.`author_type`=1 AND (`m`.`id` = `u`.`user_id` )ype = t.id
/* No WHERE clause join conditions remain, they are in the ON
clauses instead...*/
s:
{{1}}
答案 1 :(得分:1)
您不清楚您为JOIN匹配哪些列。
以下是一种做出"条件"的方法的例子。加入:
SELECT one.id
, one.type
, CASE one.type
WHEN 0 THEN two.field
WHEN 1 THEN tee.field
ELSE NULL
END AS field
FROM one
LEFT
JOIN two
ON one.type = 0
AND two.id = one.id
LEFT
JOIN three tee
ON one.type = 1
AND tee.id = one.id
要将结果集仅限制为仅包含"匹配"的行,我们会添加
WHERE two.id IS NOT NULL
OR tee.id IS NOT NULL
更新的答案(基于更新的问题)
两个最可能的解释是"只有一些行"是
1)查询中的JOIN谓词过滤掉了在另一个表中找不到匹配项的行
2)JOIN谓词是在不匹配"的列上指定的。 (例如,与users.user_id
列匹配的meals.id
列让我们感到有点奇怪。)
如果要从meals
返回所有行,是否在任何其他表(photos
或types
)中都有匹配的行,则使用OUTER JOIN操作,以meals
作为驾驶表。
例如:
SELECT m.meal_name
, m.short
, m.id
, m.time
, m.budget
, p.filename
, t.type
, CASE m.author_type
WHEN 0 THEN a.author
WHEN 1 THEN u.first_name
ELSE NULL
END AS autore
FROM meals m
LEFT
JOIN types t
ON t.id = m.type
LEFT
JOIN photos p
ON p.id = m.id
LEFT
JOIN authors a
ON m.author_type=0
AND m.id = a.id
LEFT
JOIN users u
ON m.author_type=1
AND m.id = u.user_id
请注意,我们更喜欢避免连接操作的旧式逗号语法。我们更喜欢使用JOIN
关键字代替逗号,我们更喜欢JOIN谓词位于ON
子句中,而不是WHERE
子句。
上面的查询将返回来自用餐的每一行,以及每个表中的匹配行。
再次,连接谓词将我们视为有点奇怪。例如,与来自id
的{{1}}列匹配的meals
user_id
列似乎有点奇怪。通常,我们看到在一个表中的外键与另一个表中的主键之间进行匹配。 (但我们没有看到表格架构或任何样本数据,所以这可能是有效的。它看起来很奇怪。)