我有3个(MYSQL)表,A,B和C.
我想做的是这样的事情:
SELECT * FROM a
LEFT JOIN b ON b.a_id = a.id
LEFT JOIN c on c.a_id = a.id
WHERE a.id = 1;
我在B表上有4个条目,其中B.a_id = 1:
B.id | b.a_id
1 | 1
2 | 1
3 | 1
4 | 1
我在C表上也有2个这样的条目
C.id | C.a_id
10 | 1
11 | 1
该回报给出了8个结果:
C.id | B.id
10 | 1
10 | 2
10 | 3
10 | 4
11 | 1
11 | 2
11 | 3
11 | 4
有没有办法让结果不重复相同的C和B对象,并返回更像这样的东西?
C.id | B.id
10 | 1
11 | 2
NULL | 3
NULL | 4
换句话说,我想说“给我一切映射到A = 1,但不要重复相同的C或B两次”。在我的实际数据中,我正在加入更接近10个表,并且对于所有连接表的所有排列,结果通常是数千行。
这里有一个类似的问题Connecting Multiple Tables in SQL while Limiting Exponential Results,但我希望尽可能避免内部选择。我觉得这是应该有
的数据库的常见用法答案 0 :(得分:1)
你想要的是不是简单的SQL,你不应该期望它在关系数据库中很容易。
我建议您将所有值放在一个列中,另一列指定它们的来源。这会导致大union all
类型的查询:
select 'b' as which, b.id
from a join b on b.a_id = a.id and a.id = 1
union all
select 'c', c.id
from a join c on c_aid = b.id and a.id = 1
. . .
结果并不完全符合您的要求。
如果您确实希望将数据放在不同的列中,那么您需要使用技巧为每行分配行号。然后,您可以按行号聚合结果。像这样:
select rn,
MAX(case when which = 'b' then id end) as b,
MAX(case when which = 'b' then id end) as c
from (select 'b' as which, b.id, @rn := @rn + 1 as rn
from a join b on b.a_id = a.id and a.id = 1 cross join (select @rn := 0) const
union all
select 'c', c.id, @rn := @rn + 1 as rn
from a join c on c_aid = b.id and a.id = 1 cross join (select @rn := 0) const
) t
group by rn
答案 1 :(得分:1)
这是使用SQL检索数据的基础;它检索完整行中的数据,每行具有相同的列,如SELECT
子句中请求的投影中所定义。每当我遇到类似SQL的问题时,有什么帮助我自问三个问题:
为任何特定情况回答这些问题有助于我退后一步,看看为什么某个JOIN
或GROUP BY
会给我带来麻烦;一般来说,这是因为要求数据库提供一些它没有任何概念的东西。
在您的情况下,检索数据行,数据库无法为表B提供多行,而表C 中的多行没有为您提供这些行的笛卡尔积。如果您不想要重复数据,则必须单独发布SELECT
。
回答上述问题:每一行都有表A中的所有数据,而且......呃......什么?无法将表B和C中的多行放入任意数量的列中,因此无效。没有办法从B和C返回短行数据,因为每行的长度相同。它必须为B中的每一行和C中的每一行返回一个完整的行,这将为您提供您描述的场景。
答案 2 :(得分:0)
有人可能会使用它,但似乎很容易......
你可以试试以下......
而不是左关节
SELECT * FROM a
LEFT JOIN b ON b.a_id = a.id
LEFT JOIN c on c.a_id = a.id
WHERE a.id = 1;
使用以下内部联接
SELECT * FROM a
INNER JOIN b ON b.a_id = a.id
INNER JOIN c on c.a_id = a.id
WHERE a.id = 1;
那应该有用......我想..