2009-12-29 19 views
41

Czy istnieje sposób na określenie pola zapytania nadrzędnego z podzapytania w mySQL?Jak określić pole zapytania nadrzędnego z podkwerendy w mySQL?

Na przykład:
Napisałem podstawowy program typu Tablica ogłoszeń w PHP.

W bazie danych każdy wpis zawiera: id (PK) i parent_id (id macierzystego wpisu). Jeśli wpis jest sam w sobie rodzicem, to jego parent_id jest ustawiony na 0.

Próbuję napisać zapytanie mySQL, które znajdzie każdy wpis nadrzędny i liczbę dzieci, które rodzic ma.

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

Najtrudniejsze jest to, że pierwszy id nie wie, że powinno się odnosić do drugiego id który jest poza podzapytania. Wiem, że mogę zrobić SELECT id AS id_tmp, a następnie odwołać się do niego wewnątrz podkwerendy, ale jeśli chcę również zwrócić identyfikator i zachować "id" jako nazwę kolumny, to musiałbym wykonać zapytanie, które zwraca me 2 kolumny z tych samych danych (co wydaje mi się brudny)

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

niechlujny sposób działa dobrze, ale czuję się okazją do nauczenia się czegoś tutaj więc pomyślałem, że mogę napisać pytanie.

Odpowiedz

60

Jak o:

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

lub jeśli umieścić aliasu na p1.id, można powiedzieć:

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

co jeśli wziąłem alias dla p1.id? –

+0

Co to oznacza? "wzięto alias dla"? – Don

+0

Jeśli wziąłem alias jak: "SELECT p1.id jako MYID", to jakie będzie zapytanie? –

2

Daj tabel unikalne nazwy:

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

Możesz spróbować czegoś takiego:

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 

Aby wrócić do swojej przykład użyć alias głównej tabeli w sub wybrać

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

Poniższa składnia działa w Oracle. Czy możesz sprawdzić, czy to samo działa w MYSQL? W Oracle nazywa się to podzapytaniem skalarnym.

Musisz po prostu sparować te dwie tabele inaczej, aby odróżnić je, jeśli używasz tej samej tabeli dwa razy.

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

Dzięki, Don. Miałem zagnieżdżone zapytanie, jak pokazano poniżej, a klauzula WHERE nie była w stanie określić aliasu v1. Oto kod, który nie działa:

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

Więc, po prostu dodany alias v1 znowu wewnątrz JOIN. Co sprawiło, że to działało.

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

Mam nadzieję, że będzie to pomocne dla kogoś.

Powiązane problemy