web-dev-qa-db-ja.com

mySQLのサブクエリ内から親クエリフィールドを指定するにはどうすればよいですか?

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は、それが外部にある2番目の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";

面倒な方法はうまくいきますが、ここで何かを学ぶ機会を感じているので、質問を投稿すると思いました。

48
justinl

どうですか:

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

このようなものを試すことができます

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

例に戻るには、サブ選択でメインテーブルのaliasを使用します

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

テーブルに一意の名前を付けます。

$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
Tatu Ulmanen

ありがとうドン。以下に示すようなネストされたクエリがあり、その中の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 */
);

これが誰かに役立つことを願っています。

1
Mr_Green

次の構文はOracleで機能します。同じことがMYSQLでも機能するかどうかをテストできますか? Oracleではスカラーサブクエリと呼ばれます。

同じテーブルを2回使用している場合、2つのテーブルを区別するために、2つのテーブルを別々にエイリアスする必要があります。

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
0