两个子查询的 JOIN returns 行数比两个子查询的总和多 1000 倍

JOIN of two subqueries returns 1000x more rows than the total both subqueries combined

我正在通过 PGAdmin 4.13 使用 Postgres 数据库

为了性能,我正在尝试 运行 两个单独的选择,然后对它们进行内部连接。但是,它似乎 运行 每一行都与其他每一行相对,我返回的 table 呈指数增长(实际上比单独的查询 returns 大 1000 倍。)

第一次查询returns 4320行:

SELECT * FROM schema_name.table_one WHERE resultset_name LIKE 'My test results%'

第二次查询returns 1080行:

SELECT * FROM schema_name.table_two WHERE resultset_name LIKE 'My test results%'

加入returns 518000行:D

SELECT * 
FROM
(SELECT * FROM schema_name.table_one WHERE resultset_name LIKE 'My test results%') t1 
INNER JOIN
(SELECT * FROM schema_name.table_two WHERE resultset_name LIKE 'My test results%') t2
ON t1.resultset_name = t2.resultset_name

正在尝试 运行 更传统的内连接或左连接 运行 永远...

SELECT * 
FROM schema_name.table_two
INNER JOIN schema_name.table_one 
ON schema_name.table_two.resultset_name = schema_name.table_one.resultset_name
WHERE schema_name.table_two.resultset_name LIKE 'My test results%'

注意:WHERE schema_name.table_two.resultset_name LIKE 'My test results%' 要求 schema_name.table_two. 出现在 WHERE 子句中,否则会在不明确的列名上出错。

问题 1: 为什么来自两个子选择的 JOIN 返回这么多行?我的意图是通过返回两个较小的 tables 来减少内存使用,然后仅加入那些 tables 中的数据。可以更正查询以执行此操作吗?

问题 2: 如果我的两个子选择的初始连接不能按我想要的方式工作,我如何过滤传统连接的内存使用?

编辑:为了更加清晰

问题 1:您是通过 resultset_name 加入的。我怀疑很多行在此列中具有相同的值。如果 Table_one 中有 10 行 resultset_name='My test results 1',并且 table_two 中有 20 行具有相同的值,那么结果将有 10x20=200 行相同的 resultset_name.

问题 2:大多数数据库系统自己进行此优化(您不必 restructure/rearrange 您的查询)。估计是Q1的缘故,占用资源多

你确定加入条件是t1.resultset_name = t2.resultset_name?

如果您不能确认是这种情况,请对 resultset_name 进行一些分析以找出有多少行有多少个唯一值,以及我在 Q1 中提到的场景是否适用。

编辑:如果 table_two 对相同 resultset_name 的每一行都有相同的日期(或者如果您对其中任何一个感兴趣),那么您可以减少 table_to在加入 table_one 之前,每 resultset_name 两个一行,如下所示:

SELECT * 
FROM
    schema_name.table_one t1 
    
    INNER JOIN
    (   SELECT t2a.resultset_name,
               min(t2a.date_of_experiment) as date_of_experiment
        FROM schema_name.table_two t2a 
        WHERE t2a.resultset_name LIKE 'My test results%'
        GROUP BY t2a.resultset_name) t2
    ON t1.resultset_name = t2.resultset_name
    AND t1.resultset_name LIKE 'My test results%'