JOINS 的大型查询中的 SQL 子查询链

Posted

技术标签:

【中文标题】JOINS 的大型查询中的 SQL 子查询链【英文标题】:Chain of SQL subqueries within large query of JOINS 【发布时间】:2018-02-21 18:06:16 【问题描述】:

我正在尝试使用复杂的嵌套选择操作构建 SQL 查询!

我原来的SQL查询成功加入了大约30个表,数据按要求检索!然而,30 个表中的每条获取记录 在另一个名为 (Comments) 的表中有许多记录!我想要做的是将(评论表)中的每条记录归因于它在另一个记录中的记录 按 ID 列出 30 个表,并在一个查询中一起检索它们。然而,这不是唯一的挑战,30 张表中的一些表除了 (评论表)另一个名为(附加)的表中的更多记录,所以我正在寻找主子查询中的附加子查询 外部主查询中的 LEFT JOIN。

让思路更清晰;如果没有子查询,脚本将如下所示:

$query = $mysqli->query("
SELECT 
parent1.parent1_id,
parent1.child1_id,
parent1.child2_id,
parent1.child3_id,
parent2.parent2_id,
parent2.child1_id,
parent2.child2_id,
parent2.child3_id,
child1.child1_id, 
child1.child1_content,
child2.child2_id, 
child2.child2_content,  
child3.child3_id, 
child3.child3_content
    FROM 
        parent1
    LEFT JOIN child1
        ON child1.child1_id = parent1.child1_id

    LEFT JOIN child2
        ON child2.child2_id = parent1.child2_id

    LEFT JOIN child3
        ON child3.child3_id = parent1.child3_id

    LEFT JOIN followers
        ON parent1.user_id = followers.followed_id
        AND parent1.parent1_timestamp > followers.followed_timestamp
        AND parent1.parent1_id NOT IN (SELECT removed.isub_rmv FROM removed)
        AND parent1.parent1_hide = false
    WHERE 
        followers.follower_id = $_SESSION['info']
        $portname_clause
    ORDER BY 
        parent1.parent1_timestamp DESC
    LIMIT 
        $postnumbers 
    OFFSET 
        $offset
")

// Now fetching and looping through the retrieved data

while($row = $query->fetch_assoc())

    echo $row['child1_content'];
    $subquery1 = $mysqli->query("SELECT extras.child1_id, 
    extras.extrasContent FROM extras WHERE extras.child1_id = 
   $row['child1_id']");
    while($row1 = $subquery1->fetch_assoc())
        echo $row1['extrasContent'];
    
    echo $row['child2_content'];
    $subquery2 = $mysqli->query("SELECT extras.child2_id, 
    extras.extrasContent FROM extras WHERE extras.child2_id = 
    $row['child2_id']");
    while($row2 = $subquery2->fetch_assoc())
        echo $row2['extrasContent'];
     

    echo $row['child3_content'];
    $subquery3 = $mysqli->query("SELECT extras.child3_id, 
    extras.extrasContent FROM extras WHERE extras.child3_id = 
    $row['child3_id']");
    while($row3 = $subquery3->fetch_assoc())
        echo $row3['extrasContent'];

        // Here i need to run additional query inside the subquery 3 to retrieve the (Comments table) data beside (extras table)

        $subquery4 = $mysqli->query("SELECT comments.comment_id, comments.comment FROM comments WHERE comments.child3_id = $row['child3_id'] OR comments.child3_id = $row3['child3_id']");
        while($row4 = $subquery4->fetch_assoc())
        echo $row4['comment'];
        

    

 // No sane person would make such code

因为上面的代码完全是可笑的,所以我搜索了一种更好的方法来执行它,这就是我遇到子查询的地方 概念,但是我对子查询一无所知,并且在我研究它后不久我想出了这个凌乱的代码,请在下面查看!

我没有在这里发布原始代码,因为它太长了,我包括一个我想要应用的表的虚拟示例 查询以演示该过程。

SELECT 
parent1.parent1_id,
parent1.child1_id,
parent1.child2_id,
parent1.child3_id,
parent2.parent2_id,
parent2.child1_id,
parent2.child2_id,
parent2.child3_id
FROM 
    parent1
    LEFT JOIN 
        ( SELECT 
        child1.child1_id, 
        child1.child1_content
    FROM 
        child1 
    WHERE 
        child1.child1_id = parent1.child1_id ) child1
        ( SELECT extras.extrasID, extras.extrasContent
    FROM 
        extras
    WHERE 
        extras.child1_id = child1.child1_id )
        ON parent1.child1_id = child1.child1_id
    LEFT JOIN child2
        ( SELECT 
        child2.child2_id, 
        child2.child2_content
        FROM 
           child2 
        WHERE
            child2.child2_id = parent1.child2_id )
            ( SELECT 
            extras.extrasID, 
            extras.extrasContent
            FROM 
                extras
            WHERE 
                extras.child2_id = child2.child2_id )
                    ON parent1.child2_id = child2.child2_id
                LEFT JOIN child3
                    ( SELECT 
                    child3.child3_id, 
                    child3.child3_content
                FROM 
                    child3
                WHERE 
                    child3.child3_id = parent1.child3_id )
                    ( SELECT 
                        extras.extrasID, 
                        extras.extrasContent 
                    FROM 
                        ( SELECT 
                            comments.comment_id, 
                            comments.comment
                        FROM 
                            comments 
                        WHERE 
                            comments.child3_id = extras.child3_id ) extras
                        JOIN child3 
                             ON extras.child3_id = child3.child3_id )

          ON parent1.child3_id = child3.child3_id
   LEFT JOIN followers
        ON parent1.user_id = followers.followed_id
        AND parent1.parent1_timestamp > followers.follower_timestamp
        AND parent1.parent1_id NOT IN (SELECT removed.isub_rmv FROM removed)
        AND parent1.parent1_hide = false
   WHERE 
        followers.follower_id = $_SESSION['info']
        $portname_clause
   ORDER BY 
       parent1.parent1_timestamp DESC
   LIMIT 
       $postnumbers 
   OFFSET
       $offset // <-- Sorry for the bad code formatting!

我正在使用 MySql 5.6.37

我还没有掌握子查询概念的窍门,坦率地说,我在研究它时迷失了方向,并且由于下面的注释中也提到了另一个原因。

注意:我提前道歉,我可能无法立即回复,因为我住的地方没有电、ADSL 或电话,而且我的 USB 调制解调器几乎没有信号,我每天只有两个小时平均三个小时由 desil 发电机产生的电能。我充电 我的笔记本电脑和上网,剩下的一两个小时用于其他生活用品。 我知道这个笑话在我身上,因为我正在开发一个没有电或永久互联网的网络项目。但生活并不能给予一切!哈哈。

【问题讨论】:

***.com/q/48856576/905902 您重复了之前查询中的错误。例如:) child1 ( SELECT extras 是第一个错误。先修好了。 Complex Nested SQL Query的可能重复 我正在努力,请耐心等待。 @wildplasser 我发布了我的解决方案,看看吧。 【参考方案1】:

这就是我解决问题的方法!

  SELECT 
        parent1.parent1_id,
        parent1.child1_id,
        child1.child1_id,
        child1.child1_content,
        comments.comment_id, 
        comments.comment, 
        comments.child1_id
  FROM parent1 LEFT JOIN 
(
    SELECT comments.comment_id, comments.comment, comments.child1_id
      FROM 
    (
        SELECT comments.comment_id,comments. comment, comments.child1_id
          FROM comments
    ) comments JOIN child1
        ON comments.child1_id = child1.child1_id
) comments
    ON child1.child1_id = comments.

它需要一些别名,然后就可以了。

【讨论】:

以上是关于JOINS 的大型查询中的 SQL 子查询链的主要内容,如果未能解决你的问题,请参考以下文章

如何在不破坏SQL逻辑的情况下将JOINS转换为子查询

SQL SELF 和 INNER JOINS 在一个查询中

相当于子查询的“JOIN EACH”

如何使用 JOINS 和嵌套 SELECT 优化此 SQL 查询?

如何使用 Mysql Joins 而不是嵌套子查询来实现相同的结果?

如何在 SQL SERVER 中将内联 SQL 查询转换为 JOINS 以减少加载时间