左连接在 MySQL 中为空
Posted
技术标签:
【中文标题】左连接在 MySQL 中为空【英文标题】:Left join will null in MySQL 【发布时间】:2019-07-16 08:56:09 【问题描述】:我正在寻找一种在两个(或更多)不同表中查找值时创建相对相关函数的方法。所以我有这样的表
table1:
id weight
1 0.1
2 0.15
3 0.12
6 0.21
table2:
id weight
3 0.09
6 0.2
8 0.1
11 0.13
我需要通过合并这两个表来获得相关函数。相同的行 id 将获得 10 倍的相关性,只有一个表中的 id 的行将获得“权重”相关性。
这是我需要得到的中间表(我的问题是如何制作这样的表):
id1 weight1 id2 weight2
1 0.1 null null
2 0.15 null null
3 0.12 3 0.09
6 0.21 6 0.2
null null 8 0.1
null null 11 0.13
使用此表,我可以根据需要计算相关性,但问题是从这两个表中创建这样的表。你能帮帮我吗?
我尝试了 LEFT JOIN、STRAIGHT_JOIN、LEFT OUTER JOIN,但它们的结果截然不同。
编辑:如果重要的话,我目前设想决赛桌看起来像这样:
id relevance
1 0.1
2 0.15
3 2.1
6 4.1
8 0.1
11 0.13
【问题讨论】:
看到 LEFT JOIN 和 LEFT OUTER JOIN 是完全一样的东西,这个断言似乎非常不可信 你需要一个 FULL OUTER JOIN,它是 mysql 不支持的,但它可以被模拟——尽管人们不得不质疑两个表显然存储相同类型的东西是否明智。 @Strawberry 这些表实际上是子查询,是的,它们取自同一个表,但“位置”部分非常不同。如何模拟 FULL OUTER JOIN ? 出于好奇,最终结果会是什么样子? 我想像这样e-wm.org/i/E20190222-150905-001.png 但是最终的关联函数还没有创建。 【参考方案1】:您可以为此使用FULL OUTER JOIN
,例如:
SELECT t1.id AS id1, t1.weight AS weight1, t2.id AS id2, t2.weight AS weight2
FROM table1 t1 LEFT JOIN table2 t2 ON t1.id = t2.id
UNION
SELECT t1.id AS id1, t1.weight AS weight1, t2.id AS id2, t2.weight AS weight2
FROM table1 t1 RIGHT JOIN table2 t2 ON t1.id = t2.id;
【讨论】:
FWIW,我更喜欢这样写...SELECT t1.id id1 , t1.weight weight1 , t2.id id2 , t2.weight weight2 FROM table1 t1 LEFT JOIN table2 t2 ON t2.id = t1.id UNION SELECT t1.id id1 , t1.weight weight1 , t2.id id2 , t2.weight weight2 FROM table2 t2 LEFT JOIN table1 t1 ON t1.id = t2.id;
@Strawberry 啊好吧。仅仅是可读性还是性能?
只是可读性 - 从概念上讲,我发现 LEFT JOIN 更直观
好的,我试过了,它有效,但是我认为我需要很多这样的子查询才能通过联合合并,因为我可以有 3 个甚至更多的表(最多 8 个),然后我必须将它们彼此结合在一起,对吗?这是 2^8=64 个不同的子查询...哇。【参考方案2】:
这里有几个例子:
create table Table1 ( id int primary key not null, weight decimal(10,2) not null default 0 );
create table Table2 ( id int primary key not null, weight decimal(10,2) not null default 0 );
insert into Table1 (id, weight) values (1, 0.10) ,(2, 0.15) ,(3, 0.12) ,(6, 0.21) ;
insert into Table2 (id, weight) values (3, 0.09) ,(6, 0.20) ,(8, 0.10) ,(11, 0.13) ;
编号 | id1 |重量1 | id2 |重量2 -: | ---: | ------: | ---: | ------: 1 | 1 | 0.10 | 空 | 空 2 | 2 | 0.15 | 空 | 空 3 | 3 | 0.12 | 3 | 0.09 6 | 6 | 0.21 | 6 | 0.20 8 | 空 | 空 | 8 | 0.10 11 | 空 | 空 | 11 | 0.13select id12.id as id, t1.id as id1, t1.weight as weight1, t2.id as id2, t2.weight as weight2 from (select id from Table1 union select id from Table2) id12 left join Table1 t1 on t1.id = id12.id left join Table2 t2 on t2.id = id12.id ;
编号 |关联 -: | --------: 1 | 0.10 2 | 0.15 3 | 0.21 6 | 0.41 8 | 0.10 11 | 0.13select id12.id as id, coalesce(t1.weight,0) + coalesce(t2.weight,0) as relevance from (select id from Table1 union select id from Table2) id12 left join Table1 t1 on t1.id = id12.id left join Table2 t2 on t2.id = id12.id order by id12.id;
编号 |关联 -: | --------: 1 | 0.10 2 | 0.15 3 | 0.21 6 | 0.41 8 | 0.10 11 | 0.13select id, sum(weight) as relevance from ( select id, weight from Table1 union all select id, weight from Table2 ) q group by id order by id;
db小提琴here
第二个和第三个查询返回相同的结果。 哪个更好? 这将取决于需要多少额外的字段和/或额外的计算。
【讨论】:
谢谢。顺便说一句,请注意一次使用 UNION,另一次使用 UNION ALL。了解差异很重要。UNION
只会返回唯一记录并删除重复项,而UNION ALL
只会将查询结果粘贴在一起。
我根本不需要 UNION。 table1 和 table2 的初始表是包含所有文档的同一个表,同时 table1 和 table2 只是子查询,包含来自同一个表的选定行。所以我的解决方案是用 UNION 替换子查询(从文档中选择 id)子查询。效果很好。
哦,就是这样。好吧,看起来你知道你在做什么。 :)【参考方案3】:
SELECT id
, SUM(weight) * CASE WHEN COUNT(*)=1 THEN 1 ELSE 10 END relevance
FROM
( SELECT id
, weight
FROM table1
UNION
ALL
SELECT id
, weight
FROM table2
) x
GROUP
BY id;
+----+-----------+
| id | relevance |
+----+-----------+
| 1 | 0.10 |
| 2 | 0.15 |
| 3 | 2.10 |
| 6 | 4.10 |
| 8 | 0.10 |
| 11 | 0.13 |
+----+-----------+
【讨论】:
【参考方案4】:我们可以使用存储过程和临时表来解决
CREATE PROCEDURE GetReleavance()
BEGIN
Create TEMPORARY TABLE tmpList ENGINE=MEMORY
SELECT id, weight from t1
union all
SELECT id, weight from t2
union all
SELECT id, weight from t3;
select id, sum(weight)* POW(10,COUNT(1)-1) as relevance
from tmpList
group by id;
DROP TEMPORARY TABLE IF EXISTS tmpList;
END
在过程中创建一个临时表,其中包含来自不同表的所有 id 和权重,并根据 id 获取 sum(weight)。
调用存储过程使用
CALL GetReleavance()
你可以为你想要的表数量创建联合,也不会对性能产生重大影响。
【讨论】:
好的。但是我们为什么要这样做!?! 临时表可以有索引来优化。Create Index tmpId on tmpList(id)
创建临时表后的程序将按类减少分组时间
链接***.com/questions/116423/… 解释了有关临时表的更多信息
好的。这个事实对我们有帮助吗?我正在努力看看如何:-(以上是关于左连接在 MySQL 中为空的主要内容,如果未能解决你的问题,请参考以下文章
MySQL 左连接时,查询条件查询某个字段为空或者为特定值解决方案
MySQL 左连接时,查询条件查询某个字段为空或者为特定值解决方案