2013-05-07 74 views
3

我有3个(MYSQL)表中,A,B和CSQL连接多个表,而不用返回相同的加盟ID两次

我想要做的是这样的:

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.a_id的乙表4名的条目= 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

DISTINCT是否适合您? – 2013-05-07 15:56:49

+0

在你理想的返回值中,你是不是把C = 10和B = 1任意放在同一行上?为什么?也许C = NULL和B = 1,2,3,4和B = NULL并且C = 1,2会更有意义? – mikey 2013-05-07 15:59:47

+0

我对这个关键字很熟悉,但我不确定如何在这里以一种有用的方式在上下文中使用它。如果我只是做SELECT DISTINCT(*),那不能解决问题。 – user2008476 2013-05-07 16:05:03

回答

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

这是使用SQL检索数据的基础;它会检索完整行中的数据,每行都有相同的列,如SELECT子句中所请求的投影中所定义的那样。任何时候遇到像SQL这样的问题,对我有什么帮助就是问自己三个问题:

  1. 我想要的结果行会是什么样子?也就是说,他们会有什么专栏?
  2. 数据库将如何知道如何填写每列?
  3. 数据库将如何知道要返回哪些行?

回答这些问题对于任何给定的情况下,帮助我退后一步,看看为什么一定JOINGROUP BY是造成我的麻烦;一般来说,这是因为要求数据库提供一些它根本没有任何概念的东西。

在你的情况,检索数据的行,就没有办法数据库给你从表B和多行从表C中多行不给你的那些行的笛卡尔积。如果您不想要重复数据,则必须单独发出SELECT

在回答上面的问题时表示:每一行都有来自表A的所有数据,并且......呃......什么?无法将表B和C中的多行合并到任意数量的列中,因此无法工作。无法从B和C返回短行数据,因为每行都是相同的长度。它必须为B中的每一行和C中的每一行返回一整行,这就完全给出了你描述的场景。

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; 

这应该工作...我想..

相关问题