我有两个表要连接,并且我希望每行仅连接一次。这是示例数据:
CREATE TABLE A (id smallint, val varchar(1) );
CREATE TABLE B (id smallint, val varchar(1) );
INSERT INTO A VALUES (1, 'a'), (2, 'b'), (3, 'c'), (3, 'd');
INSERT INTO B VALUES (2, 'x'), (3, 'y'), (4, 'z'), (3, 'k');
当我们加入 id 时,我们获得:
mysql> SELECT * FROM A JOIN B ON A.id = B.id;
+------+------+------+------+
| id | val | id | val |
+------+------+------+------+
| 2 | b | 2 | x |
| 3 | c | 3 | y |
| 3 | d | 3 | y |
| 3 | c | 3 | k |
| 3 | d | 3 | k |
+------+------+------+------+
我想要的是:
+------+------+------+------+ +------+------+------+------+
| id | val | id | val | | id | val | id | val |
+------+------+------+------+ or +------+------+------+------+
| 2 | b | 2 | x | | 2 | b | 2 | x |
| 3 | c | 3 | y | | 3 | d | 3 | y |
| 3 | d | 3 | k | | 3 | c | 3 | k |
+------+------+------+------+ +------+------+------+------+
顺序和排列并不重要。
这可能吗?怎么办?
根据this answer我需要指定如何选择匹配的行。在这种情况下,我想如果已使用连接表的行,则需要检查子查询;或者一种与 id 相关的计数器...但我不知道如何写这个。
编辑:
为了澄清,我希望 id 为 3 的每一行与连接表中的另一行映射,例如每一行仅映射一次(我也有兴趣知道当具有相同 id 的行数不同时会发生什么在两个表中):
(3, c) -> (3, y) [join only with the first row such as B.id = 3]
(3, d) -> (3, k) [the first row has been used, so map with (and only with) the second row such as B.id = 3]
但正如我所说,映射可以采用任何其他顺序(例如,以相反的顺序映射行)。
最佳答案
MySQL 5.6 架构设置:
CREATE TABLE A (id smallint, val varchar(1) );
CREATE TABLE B (id smallint, val varchar(1) );
INSERT INTO A VALUES (1, 'a'), (2, 'b'), (3, 'c'), (3, 'd');
INSERT INTO B VALUES (2, 'x'), (3, 'y'), (4, 'z'), (3, 'k');
查询 1:
select
aa.id as aid
, aa.val as aval
, bb.id as bid
, bb.val as bval
from (
select
@row_num :=IF(@prev_value=a.id,@row_num+1,1)AS RowInGroup
, a.id
, a.val
, @prev_value := a.id
from (
SELECT id, val
FROM A
group by id, val
/* order by ?? */
) a
CROSS JOIN (
SELECT @row_num :=1, @prev_value :=''
) vars
) aa
INNER JOIN (
select
@row_num :=IF(@prev_value=b.id,@row_num+1,1)AS RowInGroup
, b.id
, b.val
, @prev_value := b.id
from (
SELECT id, val
FROM B
group by id, val
/* order by ?? */
) b
CROSS JOIN (
SELECT @row_num :=1, @prev_value :=''
) vars
) bb on aa.id = bb.id and aa.RowInGroup = bb.RowInGroup
order by
aa.id
, aa.val
<强> Results :
| id | val | id | val |
|----|-----|----|-----|
| 2 | b | 2 | x |
| 3 | c | 3 | k |
| 3 | d | 3 | y |
nb:您可以通过在 group by id, val
的子查询中引入 order by
来影响最终结果,其中序列 RowInGroup
已计算。
关于mysql - 仅 JOIN 每行一次 — 将第 1 行排列(分布)到第 1 行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28984409/