【问题标题】:MySQL Self Full Outer JoinMySQL 自全外连接
【发布时间】:2017-09-13 14:42:16
【问题描述】:

我对 SQL 和 MySQL 非常陌生。我发现自联接是一种比较“x”的方法,其中 A 列相同,例如

表 1:

id    colA    x
-----------------
1     q1      0.1
1     q2      0.5
1     q3      0.7
2     q1      0.4
2     q2      0.9
2     q3      1.3
3     q1      0.2
3     q2      0.4
3     q3      0.1    

查询:

select a.`colA`, a.`x`, b.`x`, c.`x`
from `tab1` as a
join `tab1` as b on a.`colA` = b.`colA`
join `tab1` as c on a.`colA` = c.`colA`
where a.`id` = 1 and b.`id` = 2 and c.`id` = 3

给我:

colA    x      x      x
q1      0.1    0.4    0.2
q2      0.5    0.9    0.4
q3      0.7    1.3    0.1

太棒了!我还刚刚发现 MySQL 不能进行完全外连接,因此使用左、右或普通旧连接将为我提供 MINIMUM 行,即如果 id 缺少任何 colA 值,那么它们将完全从结果中丢失,事实上,如果我在上面的任何 id 中去掉 q1 和 q2,我会得到一行。

q3      0.7    1.3    0.1

我已经看到了很多关于如何使用 UNION / UNION ALL 来模拟完全外部联接的链接,我可以使用 frankenstein 来模拟这些链接,但这些链接并不能作为一个很好的比较表给我提供结果。有没有更简单的方法可以在 SELF 连接期间告诉查询不要忽略空值?我觉得这应该很容易,但我已经摸不着头脑了几个小时,并且在谷歌上搜索了很多答案,我认为我看不到树林,因为所有的树木。

【问题讨论】:

  • MySQL pivot table 的可能副本,如果需要动态:stackoverflow.com/questions/12004603/…
  • 内连接、左连接、全连接、联合、限制等是表上的运算符。查询是一个表达式树。将查询视为运算符的变体是没有帮助的,也许它恰好位于树的顶部,其中一棵树提供了您想要的东西。您需要考虑如何将输入转换为输出。在这里,您没有解释您的查询应该返回什么。您的“给我最小行数”不清楚,您对 do 想要什么的描述也不是很清楚。 (这似乎是三个左连接的内连接。)请阅读minimal reproducible example 并采取行动。

标签: mysql join self-join


【解决方案1】:

我会采取不同的方法;完全避免完全外连接和自连接。

我认为您所追求的是在 mySQL 中模拟一个支点,这可以通过 case 语句和具有适当分组依据的聚合来完成。

演示:http://rextester.com/NGFNJG9485

SELECT ColA
     , max(Case when ID = 1 then x end) as x1
     , max(Case when ID = 2 then x end) as x2
     , max(Case when ID = 3 then x end) as x3
FROM tab1
GROUP BY colA

给我们:

+----+------+-----+-----+-----+
|    | ColA | x1  | x2  | x3  |
+----+------+-----+-----+-----+
|  1 | q1   | 0,1 | 0,4 | 0,2 |
|  2 | q2   | 0,5 | 0,9 | 0,4 |
|  3 | q3   | 0,7 | 1,3 | 0,1 |
+----+------+-----+-----+-----+

或者如果我们消除 ID 3 的数据点,colA 'q2':

+----+------+-----+-----+------+
|    | ColA | x1  | x2  |  x3  |
+----+------+-----+-----+------+
|  1 | q1   | 0,1 | 0,4 | 0,2  |
|  2 | q2   | 0,5 | 0,9 | NULL |
|  3 | q3   | 0,7 | 1,3 | 0,1  |
+----+------+-----+-----+------+

假设

  • 您将添加更多 Q# 而不是更多 ID。换句话说,我们不需要添加更多列,因为 ID 将始终为 1、2、3。如果您确实需要更多列 (Id),只需添加其他案例;或使用顶级评论第二个链接中提到的动态 SQL。
  • ID 和 colA 是唯一的。如果存在重复项,那么我们需要讨论应该呈现什么 x 值。平均?和?什么?否则,min/max/avg 都会起作用。

这会根据需要处理空值,因为只有空值的列的最大值是空值,我们也可以coalesce() 结果显示 0,如果优先于空值。例如:coalesce(max(Case when ID = 3 then x end),0) as x3

给我们:

+----+------+-----+-----+-----+
|    | ColA | x1  | x2  | x3  |
+----+------+-----+-----+-----+
|  1 | q1   | 0,1 | 0,4 | 0,2 |
|  2 | q2   | 0,5 | 0,9 | 0,0 |
|  3 | q3   | 0,7 | 1,3 | 0,1 |
+----+------+-----+-----+-----+

【讨论】:

  • 这一切看起来都很棒。我想我真的问错了问题,似乎我需要模拟一个数据透视表。我没有时间正确地回顾这一秒,但我想说谢谢,最初的想法是不幸的是 ID 计数将一直在上升,所以我想知道我是否可以创建一个存储过程来处理 ID 案例...除此之外,我迫不及待想尝试一下。
  • Bluefeet 是动态枢轴之王。一个很好的动态示例(顶部 cmets 中的第二个链接) 至于提出错误的问题:这是我们一直在寻找的东西,它被称为 XY problem。而不是解决您所询问的症状;我们要解决根本原因。在我看来,您走错了路,使解决方案越来越难;当您真正需要的(我认为)是 mySQL 中的一个支点时(直到您的最后评论,我才知道它是动态的还是静态的)
猜你喜欢
  • 2013-03-11
  • 2021-10-12
  • 2015-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-22
  • 2017-05-24
  • 2017-06-09
相关资源
最近更新 更多