我有一个表R,其中包含表P的外键。表P中有一列,告诉我表P中的记录是哪种类型。与列P.type中的可能值相关的表存在。因此,如果在P.type中为' C‘,则表示一个名为C的表,如果值为' D’,则表示一个名为D的表。
现在,我想要一个SELECT语句,根据P.type分别从表C或D中给出值。为了使其更加复杂,结果中列的数目/类型将有所不同。
SELECT r.id, r.pid, p.type,
FROM R r
LEFT JOIN P p ON r.pid = p.pid
WHERE r.id = 123 LIMIT 1;现在我得到了P表的记录。根据列类型的值,我想决定我要加入哪个表(C还是D)。如果我必须加入表D,返回的列(结果集)应保持原样,但如果必须连接表C,则应返回另一列。因此,SELECT子句将从
选择r.id,r.pid,p.type。
至
选择r.id,r.pid,p.type,c.name。
Preudocode:
SELECT r.id, r.pid, p.type(, c.name) -- c.name my or may not be in the result depending on the joined table
FROM R r
LEFT JOIN P p ON r.pid = p.pid
if p.type = 'D' LEFT JOIN D d ON d.pid = p:pid end
if p.type = '' LEFT JOIN C c ON c.pid = p:pid end
WHERE r.id = 123 LIMIT 1;p.type的值可以从C和D增加到E,F,G,……)我倾向于只加入p.type指定的一个表,而不是使用UNION (首先是所有可能的表)。Whereby...since结果中的列数不同,UNION尝试以错误代码1222结尾:
使用的SELECT语句有不同的列数。
这有可能..。怎么做呢?
发布于 2014-06-12 12:16:17
您的伪代码可以实现为:
SELECT r.id, r.pid, p.type, coalesce(d.name, c.name)
FROM R r LEFT JOIN
P p
ON r.pid = p.pid LEFT JOIN
D d
ON p.type = 'D' and d.pid = p.pid LEFT JOIN
C c
ON p.type = '' and c.pid = p.pid end
WHERE r.id = 123
LIMIT 1;假设表C和D没有匹配的多行,这将有效。如果是这样,您可能需要预先聚合结果或使用子查询。
发布于 2014-06-12 12:20:18
@GordonLinoff的一个类似的但可替代的答案是将表C和D合并到一个表中。
这可以通过一个真正的单表、一个视图或一个内联视图来完成,后者我将在下面展示.
SELECT
r.id,
r.pid,
p.type,
z.name
FROM
R AS r
LEFT JOIN
P AS p
ON r.pid = p.pid
LEFT JOIN
(
SELECT 'D' AS type, pid, '' AS name FROM D
UNION ALL
SELECT '' AS type, pid, name AS name FROM C
)
AS z
ON z.type = p.type
AND z.pid = p.pid
WHERE
r.id = 123
LIMIT
1
;这种结构通常可以通过减少重复来简化代码,但也可以帮助优化器(取决于索引等)减少联接中所需的工作量。
注意:因为联合的表在第一个字段中有标量常量,而且由于联接中使用了该字段,所以优化器能够(取决于RDBMS)避免对两个表进行冗余连接。(有足够的信息来“知道”要加入哪个表。)
编辑: OP发表评论后的
如果这两个表有很大的差异,使UNION变得不切实际,那么使用两个LEFT JOIN可能是最好的选择。
https://stackoverflow.com/questions/24184078
复制相似问题