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

时间:2009-12-29 06:36:59

标签: php mysql subquery parent-child

有没有办法在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";

凌乱的方式很好,但我觉得有机会在这里学到一些东西,所以我想我会发布这个问题。

6 个答案:

答案 0 :(得分:68)

怎么样:

$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";

答案 1 :(得分:4)

你可以试试这样的事情

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

答案 2 :(得分:2)

为表格提供唯一名称:

$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";

答案 3 :(得分:1)

谢谢唐。我有一个嵌套查询,如下所示,其中的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 */
);

所以,我刚刚在v1内添加了别名JOIN。这使它发挥作用。

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 */
);

希望这会对某人有所帮助。

答案 4 :(得分:0)

以下语法适用于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 :(得分:0)

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");