Mysql 从两个表中选择匹配的对
我需要从包含相似结构数据的两个表中选择匹配对。这里的Matched Pair是指在“match”列中相互引用的两行 单表匹配对示例:Mysql 从两个表中选择匹配的对,mysql,sql,Mysql,Sql,我需要从包含相似结构数据的两个表中选择匹配对。这里的Matched Pair是指在“match”列中相互引用的两行 单表匹配对示例: TABLE ---- id | matchid 1 | 2 2 | 1 ID 1和ID 2是匹配的对,因为它们各自都有一个对应于另一个的匹配项 现在真正的问题是:选择两个表中出现的匹配对的最快方法是什么: Table ONE (id, matchid) Table TWO (id, matchid) 示例数据: ONE
TABLE
----
id | matchid
1 | 2
2 | 1
ID 1和ID 2是匹配的对,因为它们各自都有一个对应于另一个的匹配项
现在真正的问题是:选择两个表中出现的匹配对的最快方法是什么:
Table ONE (id, matchid)
Table TWO (id, matchid)
示例数据:
ONE TWO
---- ----
id | matchid id | matchid
1 | 2 2 | 3
2 | 3 3 | 2
3 | 2
4 | 5
5 | 4
所需的结果是ID为2和3的单行
RESULT
----
id | id
2 | 3
这是因为表1和表2中的2和3是匹配对。4和5是表1中的匹配对,但不是表2中的匹配对,因此我们不选择它们。1和2根本不是匹配对,因为2没有1的匹配项
我可以从一个表中获得匹配的配对:
SELECT a.id, b.id
FROM ONE a JOIN ONE b
ON a.id = b.matchid AND a.matchid = b.id
WHERE a.id < b.id
我应该如何构建一个只选择两个表中出现的匹配对的查询
我应该:
为每个表选择上面的查询以及它们一起存在的位置?
为每个表选择上面的查询并将它们连接在一起?
选择上面的查询,然后两次联接表,一次联接“id”,一次联接“matchid”?
为每个表选择上面的查询并循环,以便在php中对它们进行比较?
以某种方式过滤表2,这样我们只需查看表1中匹配对中的ID?
做些完全不同的事?
由于这是一个效率问题,值得注意的是,匹配将非常稀疏,可能是1/1000或更少,每个表将有100000多行。我想我明白你的意思。您希望筛选两个表上存在对的记录
我想我明白你的意思了。您希望筛选两个表上存在对的记录 请尝试以下查询: 已编辑的查询: 请尝试以下查询: 已编辑的查询:
Naive版本,它检查需要存在的所有四行:
-- EXPLAIN ANALYZE
WITH both_one AS (
SELECT o.id, o.matchid
FROM one o
WHERE o.id < o.matchid
AND EXISTS ( SELECT * FROM one x WHERE x.id = o.matchid AND x.matchid = o.id)
)
, both_two AS (
SELECT t.id, t.matchid
FROM two t
WHERE t.id < t.matchid
AND EXISTS ( SELECT * FROM two x WHERE x.id = t.matchid AND x.matchid = t.id)
)
SELECT *
FROM both_one oo
WHERE EXISTS (
SELECT *
FROM both_two tt
WHERE tt.id = oo.id AND tt.matchid = oo.matchid
);
这个比较简单:
-- EXPLAIN ANALYZE
WITH pair AS (
SELECT o.id, o.matchid
FROM one o
WHERE EXISTS ( SELECT * FROM two x WHERE x.id = o.id AND x.matchid = o.matchid)
)
SELECT *
FROM pair pp
WHERE EXISTS (
SELECT *
FROM pair xx
WHERE xx.id = pp.matchid AND xx.matchid = pp.id
)
AND pp.id < pp.matchid
;
Naive版本,它检查需要存在的所有四行:
-- EXPLAIN ANALYZE
WITH both_one AS (
SELECT o.id, o.matchid
FROM one o
WHERE o.id < o.matchid
AND EXISTS ( SELECT * FROM one x WHERE x.id = o.matchid AND x.matchid = o.id)
)
, both_two AS (
SELECT t.id, t.matchid
FROM two t
WHERE t.id < t.matchid
AND EXISTS ( SELECT * FROM two x WHERE x.id = t.matchid AND x.matchid = t.id)
)
SELECT *
FROM both_one oo
WHERE EXISTS (
SELECT *
FROM both_two tt
WHERE tt.id = oo.id AND tt.matchid = oo.matchid
);
这个比较简单:
-- EXPLAIN ANALYZE
WITH pair AS (
SELECT o.id, o.matchid
FROM one o
WHERE EXISTS ( SELECT * FROM two x WHERE x.id = o.id AND x.matchid = o.matchid)
)
SELECT *
FROM pair pp
WHERE EXISTS (
SELECT *
FROM pair xx
WHERE xx.id = pp.matchid AND xx.matchid = pp.id
)
AND pp.id < pp.matchid
;
你不是想加入a.matchid=b.matchid吗?@sashkello-不完全是。表中必须有两行,每行相互匹配。那么这些匹配必须同时存在于两个表中。我不明白你的意思。这似乎是一个简单的问题,你把它复杂化了……请尝试下面我的答案:请注意,在多个表中存在id和matchid之间的关系等数据可能被认为是数据库设计不好的标志,因为它是多余的,因此容易出现不一致。你不是在尝试加入a.matchid=b.matchid吗?@sashkello-不完全是这样。表中必须有两行,每行相互匹配。那么这些匹配必须同时存在于两个表中。我不明白你的意思。这似乎是一个简单的问题,您把它复杂化了……请尝试下面我的答案:请注意,在多个表中存在id和matchid之间的关系这样的数据可能被认为是数据库设计不好的标志,因为它是冗余的,因此容易出现不一致。
-- EXPLAIN ANALYZE
WITH pair AS (
SELECT o.id, o.matchid
FROM one o
WHERE EXISTS ( SELECT * FROM two x WHERE x.id = o.id AND x.matchid = o.matchid)
)
SELECT *
FROM pair pp
WHERE EXISTS (
SELECT *
FROM pair xx
WHERE xx.id = pp.matchid AND xx.matchid = pp.id
)
AND pp.id < pp.matchid
;