MySQL两表INNER JOIN,LEFT JOINED到第三表,只有一行的最小值

时间:2018-09-18 22:55:07

标签: php mysql sql mysqli pdo

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

我有一个查询,该查询在两个表上执行INNER JOIN,而此联接大大限制了我的整体数据集。然后,我想左联接到第三张表上,但我只想要第三张表中的一条记录。之所以选择左联接,是因为不是INNER JOIN的每个结果在第3个表中都有匹配项。像这样:

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

此查询返回的记录太多,因为第三个表包含具有匹配的 code 的多个记录。我只想要第一个与最低 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

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

在MySQL 8.0中,您可以尝试对每个代码使用row_number(),并在display_order的子查询中按table3进行排序。然后左移连接该结果并检查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);

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


编辑:

如果不想重复ORDER BY子句中的子查询,也可以按列序进行排序。例如:

...
ORDER BY 1, 6;