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

Posted

技术标签:

【中文标题】如何在 MySQL 的子查询中指定父查询字段?【英文标题】:How to specify the parent query field from within a subquery in MySQL? 【发布时间】:2010-12-30 16:52:42 【问题描述】:

例如: 我已经用 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";

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

【问题讨论】:

【参考方案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");

【讨论】:

以上是关于如何在 MySQL 的子查询中指定父查询字段?的主要内容,如果未能解决你的问题,请参考以下文章

我必须在 Android Manifest 中指定父活动名称吗?

如何使用多个条件查找查询在 MongoDB 中指定字段?

如何SQL查询字段值包含于字符串

求助啊,tp下,mongodb如何查询后只返回某个字段值

在构建 Java GraphQL API 时,如何避免从数据库中过度获取(即仅获取查询中指定的字段)?

如何重写此 MySQL 查询,使其不会引发此错误:您无法在 FROM 子句中指定目标表 'crawlLog' 进行更新?