MySQL 双表 INNER JOIN , LEFT JOINED 到第三张表,只有一行具有最低值

Posted

技术标签:

【中文标题】MySQL 双表 INNER JOIN , LEFT JOINED 到第三张表,只有一行具有最低值【英文标题】:MySQL two-table INNER JOIN , LEFT JOINED onto third table with only one row with lowest value 【发布时间】:2019-02-23 00:37:23 【问题描述】:

我四处搜索,找到了我正在寻找的 near example,但它在我的情况下不起作用。

我有一个查询,它在两个表上执行 INNER JOIN,这个连接极大地限制了我的整个数据集。然后我想 LEFT JOIN 到第三个表中,但我只想要第三个表中的一条记录。左连接的原因是因为并非 INNER JOIN 的每个结果在第三张表中都有匹配项。像这样的:

SELECT DISTINCT t1.code, t2.id, t2.code, t3.id, t3.source_title, t3.display_order
FROM table1 t1
INNER JOIN table2 t2 ON t2.code=t1.code AND t2.type=0
LEFT JOIN table3 t3 ON t3.code=t1.code
ORDER BY t1.code, t3.display_order

此查询返回的记录过多,因为第三个表包含多个具有匹配代码的记录。我只想要第一个与最低 display_order 值匹配的记录,不幸的是,我无法将记录限制为 display_order=1,因为最低显示顺序并不总是一个。

重要提示:此查询返回的 t3.id 值(如果有)必须与 display_order 值最低的记录相对应。也就是说,它不起作用如果查询正确返回了最低的 display_order 值,但 t3.id 值对应于表 3 中的其他记录。

这甚至可能吗?任何帮助将不胜感激。

编辑:根据尼克的建议,我已经尝试过了,这似乎有效。我会做一些验证并报告:

SELECT DISTINCT t1.code, t2.*, sq.id, sq.source_title, sq.display_order
FROM table1 t1
INNER JOIN table2 p ON t2.code=t1.code AND t2.type=0
LEFT JOIN (
    SELECT t3.*
    FROM table3 t3
    WHERE t3.display_order=(
        SELECT MIN(display_order)
        FROM table3 t3a 
        WHERE t3a.code = t3.code
    )
) sq ON sq.code=t1.code
ORDER BY t1.code, sq.display_order

【问题讨论】:

您能提供一些示例数据并期待结果吗? @D-Shih 我需要一些时间。数据是专有的。 【参考方案1】:

您应该可以将LEFT JOIN 中的table3 替换为

(SELECT * 
 FROM table3 t3 
 WHERE display_order = (SELECT MIN(display_order) 
                        FROM table3 t3a 
                        WHERE t3a.code = t3.code)
) t3

【讨论】:

【参考方案2】:

mysql 8.0 中,您可以尝试对每个代码使用 row_number(),并在来自 table3 的子查询中按 display_order 排序。然后左加入该结果并检查 row_number() 是否等于 1。

SELECT DISTINCT
       t1.code,
       t2.id,
       t2.code,
       t3.id,
       t3.source_title,
       t3.display_order
       FROM table1 t1
            INNER JOIN table2 t2
                       ON t2.code = t1.code
            LEFT JOIN (SELECT t3.id,
                              t3.source_title,
                              t3.display_order,
                              t3.code,
                              row_number() OVER (PARTITION BY t3.code
                                                 ORDER BY t3.display_order) rn
                              FROM table3 t3) t3
                      ON t3.code = t1.code
       WHERE t2.type = 0
             AND t3.rn = 1
       ORDER BY t1.code,
                t3.display_order;

在较低版本中,您可以尝试按display_orderLIMIT 1 排序的相关子查询(仅获取一条记录)。

SELECT DISTINCT
       t1.code,
       t2.id,
       t2.code,
       (SELECT t3.id
               FROM table3 t3
               WHERE t3.code = t1.code
               ORDER BY t3.display_order,
                        t3.id
               LIMIT 1) id,
       (SELECT t3.source_title
               FROM table3 t3
               WHERE t3.code = t1.code
               ORDER BY t3.display_order,
                        t3.id
               LIMIT 1) source_title,
       (SELECT t3.display_order
               FROM table3 t3
               WHERE t3.code = t1.code
               ORDER BY t3.display_order,
                        t3.id
               LIMIT 1) display_order
       FROM table1 t1
            INNER JOIN table2 t2
                       ON t2.code = t1.code
       WHERE t2.type = 0
       ORDER BY t1.code,
                (SELECT t3.display_order
                        FROM table3 t3
                        WHERE t3.code = t1.code
                              ORDER BY t3.display_order,
                                       t3.id
                              LIMIT 1);

我假设,table3 中的 display_order 不是唯一的,但 id 是唯一的。所以我在子查询中的ORDER BY 子句中添加了id,以确保在每个子查询中选择相同的记录。如果display_order 是唯一的,您可以从ORDER BY 子句中删除id


编辑:

如果您不想重复(整体)ORDER BY 子句中的子查询,您也可以按列序号排序。例如:

...
ORDER BY 1, 6;

【讨论】:

我的工作站(我计划很快升级)有一个更旧的版本,5.6.33。我会看看我是否可以让这个其他查询工作——虽然这很冗长。 我想说的是,您拥有的第二个产品(这是一件艺术品)确实提供了我所追求的确切数据集,但我似乎无法使用它(例如,更改整体排序顺序)。 @S.Imp:不是 100% 确定问题出在哪里,但我猜测了一下。也许我的编辑有帮助? 啊哈!我已经对其进行了排序等。也就是说,它有点冗长/麻烦。我用更紧凑的解决方案编辑了我的原始帖子。

以上是关于MySQL 双表 INNER JOIN , LEFT JOINED 到第三张表,只有一行具有最低值的主要内容,如果未能解决你的问题,请参考以下文章

mysql 里面JOIN 和 INNER JOIN 区别是啥

MySQL中inner join 和 cross join 的区别

mysql inner join如何显示记录为空的数据

MySQL left join right join inner join

Mysql之inner join,left join,right join详解

Mysql 连接(left join, right join, inner join ,full join)