sql >> Databasteknik >  >> RDS >> Mysql

MySQL:hur frågar man förälder-barn?

Här är en idé. Men det är baserat på många antaganden om hur din data är inställd. Ständigt ökande ID:n ner i trädet, bara två nivåer, etc.

SELECT f.foo_id,f.foo_parent_id FROM foo f
foo f

--ge mig det översta X-talet av parent_ids(Detta är bra, justera bara LIMIT 10 för att variera antalet föräldranivåer som ska visas)

INNER JOIN 
(select foo_id from foo where foo_parent_id is null order by foo_parent_id 
LIMIT 10
) top_foo_parent
      on isnull(f.foo_parent_id,f.foo_id) = top_foo_parent.foo_id
WHERE

(Den här delen är lite hackig, eftersom du måste lägga en allt längre sträng av dessa för att komma förbi två barn)

--det är det första barnet, eller...

(f.foo_id in (select MIN(foo_id) from foo fc1 where fc1.foo_parent_id =f.foo_parent_id)
 )
 or

--det är det andra barnet, eller...

(f.foo_id in (select MIN(foo_id) from foo fc1 where fc1.foo_parent_id =f.foo_parent_id  and fc1.foo_id not in (select MIN(foo_id) from foo fc2 where fc2.foo_parent_id=f.foo_parent_id))
 )
 or 

--det är föräldern

 f.foo_parent_id is null
order by isnull(f.foo_parent_id,f.foo_id)*100 + f.foo_id

Så vad vi gör här är i princip att sortera efter kolumnen parent_id och sedan underkolumnerna under den med en liten vridning. Om parentid-kolumnen är NULL använder vi det faktiska ID:t. Det betyder att för beställningsändamål ser vårt bord ut så här:

==============================================================================
| foo_id | foo_parent_id |   isnull(f.foo_parent_id,f.foo_id)
==============================================================================
| 1      | NULL           |         (1)
| 2      | NULL           |         (2)
| 3      |  1             |         1
| 4      |  2             |         2
| 5      |  1             |         1
| 7      |  2             |         2
----------------------------------------------------------------------

Sedan multiplicerar vi den beställningskolumnen *100

==============================================================================
| foo_id | foo_parent_id |   isnull(f.foo_parent_id,f.foo_id)*100
==============================================================================
| 1      | NULL           |         100
| 2      | NULL           |         200
| 3      |  1             |         100
| 4      |  2             |         200
| 5      |  1             |         100
| 7      |  2             |         200
----------------------------------------------------------------------

och slutligen lägger vi till vår foo_id-kolumn till den

==============================================================================
| foo_id | foo_parent_id |   isnull(f.foo_parent_id,f.foo_id)*100 + foo_id
==============================================================================
| 1      | NULL           |         101
| 2      | NULL           |         202
| 3      |  1             |         103
| 4      |  2             |         204
| 5      |  1             |         105
| 7      |  2             |         207
----------------------------------------------------------------------

Nu ordnar vi tabellen efter den virtuella kolumnen och...

==============================================================================
| foo_id | foo_parent_id |   ORDER BY isnull(f.foo_parent_id,f.foo_id)*100 + foo_id
==============================================================================
| 1      | NULL           |         101
| 3      |  1             |         103
| 5      |  1             |         105
| 2      | NULL           |         202    
| 4      |  2             |         204
| 7      |  2             |         207
----------------------------------------------------------------------

Där kör vi!



  1. JSON_EXTRACT() – Returnera data från ett JSON-dokument i MySQL

  2. Dialekt måste anges uttryckligen från v4.0.0

  3. Pivot utan aggregatfunktion i MSSQL 2008 R2

  4. postgresql ansluta 2 tabeller