【问题标题】:How to specify the parent query field from within a subquery in MySQL?如何在 MySQL 的子查询中指定父查询字段?
【发布时间】:2025-11-24 05:30:02
【问题描述】:

如何在 MySQL 的子查询中指定父查询字段?

例如:
我已经用 PHP 编写了一个基本的公告板类型程序。

在数据库中,每个帖子都包含:id(PK) 和 parent_id(父帖子的 id)。如果帖子本身是父级,则其 parent_id 设置为 0。

我正在尝试编写一个 mySQL 查询,该查询将查找每个父帖子以及该父母拥有的孩子的数量。

$query = "SELECT id, (
      SELECT COUNT(1) 
      FROM post_table 
      WHERE parent_id = id
) as num_children
FROM post_table
WHERE parent_id = 0";

棘手的部分是第一个 id 不知道它应该引用子查询之外的第二个 id。我知道我可以执行 SELECT id AS id_tmp 然后在子查询中引用它,但是如果我还想返回 id 并将“id”作为列名,那么我必须做一个返回的查询我 2 列具有相同的数据(这对我来说似乎很乱)

$query = "SELECT id, id AS id_tmp, 
            (SELECT COUNT(1)
            FROM post_table
            WHERE parent_id = id_tmp) as num_children
         FROM post_table
         WHERE parent_id = 0";

乱七八糟的方法很好用,但我觉得有机会在这里学习一些东西,所以我想我会发布这个问题。

【问题讨论】:

    标签: php mysql subquery parent-child


    【解决方案1】:

    为表指定唯一名称:

    $query = "SELECT a.id, (SELECT COUNT(1) FROM post_table b WHERE parent_id = a.id) as num_children FROM post_table a WHERE a.parent_id = 0";
    

    【讨论】:

      【解决方案2】:

      怎么样:

      $query = "SELECT p1.id, 
                       (SELECT COUNT(1) 
                          FROM post_table p2 
                         WHERE p2.parent_id = p1.id) as num_children
                  FROM post_table p1
                 WHERE p1.parent_id = 0";
      

      或者如果你在 p1.id 上加上一个别名,你可能会说:

      $query = "SELECT p1.id as p1_id, 
                       (SELECT COUNT(1) 
                          FROM post_table p2 
                         WHERE p2.parent_id = p1.id) as num_children
                  FROM post_table p1
                 WHERE p1.parent_id = 0";
      

      【讨论】:

      • 如果我为 p1.id 取了别名怎么办?
      • 这是什么意思? “取别名”?
      • 如果我使用了类似的别名:“SELECT p1.id as MYID”,那么查询会是什么?
      • @Er.KT,我已经对在 id 上显示别名的答案进行了编辑。
      • 哦,明白了,所以我们不必在子查询条件中传递别名(WHERE p2.parent_id = p1.id(这里不是'p1_id')),对吧?
      【解决方案3】:

      你可以试试这样的

      SELECT  pt.id,
              CountTable.Cnt
      FROM    post_table pt LEFT JOIN
              (
                  SELECT  parent_id,
                          COUNT(1) Cnt
                  FROM    post_table
                  WHERE   parent_id <> 0
                  GROUP BY parent_id
              ) CountTable ON pt.id = CountTable.parent_id
      WHERE   pt.parent_id = 0
      

      回到你的例子,在子选择中使用主表的别名

      SELECT  pt.id,
              (SELECT COUNT(1) FROM post_table WHERE parent_id = pt.id) 
      FROM    post_table pt
      WHERE   pt.parent_id = 0
      

      【讨论】:

        【解决方案4】:

        以下语法适用于 Oracle。你能测试一下是否同样适用于 MYSQL 吗? 在 Oracle 中称为标量子查询。

        如果您两次使用同一个表,您只需对这两个表进行不同的别名以区分它们。

        sql> select empno,
          2         (select dname from dept where deptno = emp.deptno) dname
          3    from emp 
          4    where empno = 7369;
        
             EMPNO DNAME
        ---------- --------------
              7369 RESEARCH
        
        sql> select parent.empno,
          2         (select mgr from emp where empno = parent.empno) mgr
          3    from emp parent
          4    where empno = 7876;
        
             EMPNO        MGR
        ---------- ----------
              7876       7788
        

        【讨论】:

          【解决方案5】:

          谢谢唐。我有一个嵌套查询,如下所示,其中的WHERE 子句无法确定别名v1。这是不起作用的代码:

          Select 
              teamid,
              teamname
          FROM
              team as t1
          INNER JOIN (
              SELECT 
                  venue_id, 
                  venue_scores, 
                  venue_name 
              FROM venue 
              WHERE venue_scores = (
                  SELECT 
                      MAX(venue_scores) 
                  FROM venue as v2 
                  WHERE v2.venue_id = v1.venue_id      /* this where clause wasn't working */
              ) as v1    /* v1 alias already present here */
          );
          

          所以,我只是在JOIN 中再次添加了别名v1。这使它起作用了。

          Select 
              teamid,
              teamname
          FROM
              team as t1
          INNER JOIN (
              SELECT 
                  venue_id, 
                  venue_scores, 
                  venue_name 
              FROM venue as v1              /* added alias v1 here again */
              WHERE venue_scores = (
                  SELECT 
                      MAX(venue_scores) 
                  FROM venue as v2 
                  WHERE v2.venue_id = v1.venue_id   /* Now this works!! */
              ) as v1     /* v1 alias already present here */
          );
          

          希望这对某人有所帮助。

          【讨论】:

            【解决方案6】:

            MySQL 8 中子查询中的父查询字段。

            我正在使用嵌套查询根据 tblgamescores 中的用户名选择游戏分数。

            SELECT 
                GameScoresID, 
                (SELECT Username FROM tblaccounts WHERE AccountID = FromAccountID) AS FromUsername, 
                (SELECT Username FROM tblaccounts WHERE AccountID = ToAccountID) AS ToUsername,
                (SELECT Username FROM tblaccounts WHERE AccountID = WinAccountID) AS WinUsername,
                (SELECT Username FROM tblaccounts WHERE AccountID = LossAccountID) AS LossUsername,
                FromUserScore,
                ToUserScore 
            FROM tblgamescores a 
            WHERE FromAccountID = (SELECT AccountID FROM tblaccounts WHERE Username = "MHamzaRajput");
            

            【讨论】: