Est-il possible de spécifier le champ de requête parent à partir d'une sous-requête dans MySQL?
Par exemple:
J'ai écrit un programme de base de type babillard en PHP.
Dans la base de données, chaque publication contient: id (PK) et parent_id (id de la publication parente). Si la publication est elle-même un parent, son parent_id est défini sur 0.
J'essaye d'écrire une requête de MySQL qui trouvera chaque poste parent et le nombre d'enfants qu'il a.
$query = "SELECT id, (
SELECT COUNT(1)
FROM post_table
WHERE parent_id = id
) as num_children
FROM post_table
WHERE parent_id = 0";
La difficulté réside dans le fait que le premier id ne sait pas qu’il devrait faire référence au second id situé en dehors de la sous-requête. Je sais que je peux faire une sélection SELECT id AS id_tmp et y faire référence à l'intérieur de la sous-requête, mais si je souhaite également renvoyer l'ID et conserver "id" en tant que nom de colonne, il me faudra alors effectuer une requête renvoyant moi 2 colonnes avec les mêmes données (ce qui me semble malpropre)
$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";
La manière désordonnée fonctionne bien, mais je me sens comme une occasion d'apprendre quelque chose ici, alors j'ai pensé poser la question.
Que diriez-vous:
$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";
ou si vous mettez un pseudonyme sur p1.id, vous pourriez dire:
$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";
Tu pourrais essayer quelque chose comme ça
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
Pour revenir à votre exemple, utilisez le alias de la table principale dans la sous-sélection
SELECT pt.id,
(SELECT COUNT(1) FROM post_table WHERE parent_id = pt.id)
FROM post_table pt
WHERE pt.parent_id = 0
Attribuez aux tables des noms uniques:
$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";
La syntaxe suivante fonctionne dans Oracle. Pouvez-vous tester si la même chose fonctionne aussi dans MYSQL? Cela s'appelle une sous-requête scalaire dans Oracle.
Si vous utilisez deux fois la même table, il vous suffira d’aliaser différemment les deux tables pour les distinguer.
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
Merci Don. Comme indiqué ci-dessous, ma requête était imbriquée et une clause WHERE
ne permettait pas de déterminer l'alias v1
. Voici le code qui ne fonctionne pas:
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 */
);
Donc, je viens d'ajouter le pseudonyme v1
à nouveau dans la JOIN
. Ce qui a fait que ça marche.
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 */
);
J'espère que cela sera utile pour quelqu'un.