How do I order by parent then child?
From your comment, if you know there are only two levels, there is an easy solution:
select *
from @Features feat
order by
case
when ParentID = 0
then Feature
else (
select Feature
from @Features parent
where parent.FeatureID = feat.ParentID
)
end
, case when ParentID = 0 then 1 end desc
, Feature
- Sort by the name of the root element: for the root, this is Feature column. For the children, look up the root's name with a subquery.
- Sort the root on top
- Sort the children by name
Example at SE Data.
MySql: ORDER BY parent and child
Including sorting children by id:
ORDER BY COALESCE(parent, id), parent IS NOT NULL, id
SQL Fiddle example
Explanation:
COALESCE(parent, id)
: First sort by (effectively grouping together) the parent's id.parent IS NOT NULL
: Put the parent row on top of the groupid
: Finally sort all the children (same parent, andparent
is not null)
SQL Order by parent and child
You want your data ordered in alphabetical order and depth first.
A common solution for this is to traverse the structure from the top element, concatenating the path to each item as you go. You can then directly use the path for ordering.
Here is how to do it in MySQL 8.0 with a recursive query
with recursive cte(venueID, venueName, mainVenueID, path, depth) as (
select v.venueID, v.venueName, cast(null as char(100)), venueName, 0
from tblAdmVenue v
where not exists (select 1 from tblAdmVenueLink l where l.subVenueID = v.venueID)
union all
select v.venueID, v.venueName, c.venueID, concat(c.path, '/', v.venueName), c.depth + 1
from cte c
inner join tblAdmVenueLink l on l.mainVenueID = c.venueID
inner join tblAdmVenue v on v.venueID = l.subVenueID
)
select * from cte order by path
The anchor of the recursive query selects top nodes (ie rows whose ids do not exist in column subVenueID
of the link table). Then, the recursive part follows the relations.
As a bonus, I added a level
column that represents the depth of each node, starting at 0 for top nodes.
Demo on DB Fiddle:
venueID | venueName | mainVenueID | path | depth
:------ | :-------------- | :---------- | :------------------------- | ----:
LA47 | Banquet | null | Banquet | 0
LA43 | Big Room | null | Big Room | 0
LA45 | Room Daisy | LA43 | Big Room/Room Daisy | 1
LA46 | Room Rose | LA43 | Big Room/Room Rose | 1
LA48 | Split 1 | LA46 | Big Room/Room Rose/Split 1 | 2
LA44 | Hall | null | Hall | 0
LA49 | Meeting Room WP | LA44 | Hall/Meeting Room WP | 1
SQL Server Order first by ParentID, then Child
you can achieve this using CTE
;with cte as
(
select
ParentAssetID,
ChildAssetID,
AssetName,
cast(row_number()over(partition by ParentAssetID order by AssetName) as varchar(max)) as [path],
0 as level,
row_number()over(partition by ParentAssetID order by AssetName) / power(10.0,0) as x
from Assets
where ParentAssetID =956
union all
select
t.ParentAssetID,
t.ChildAssetID,
t.AssetName,
[path] +'-'+ cast(row_number()over(partition by t.ParentAssetID order by t.AssetName) as varchar(max)),
level+1,
x + row_number()over(partition by t.ParentAssetID order by t.AssetName) / power(10.0,level+1)
from
cte
join Assets t on cte.ChildAssetID = t.ParentAssetID
)
select
ParentAssetID,
ChildAssetID,
AssetName,
[path],
x
from cte
order by x
How to Order table records with parent followed by child using SQL Query
You need a recursive query that carries the root ID through all levels, then you can sort the rows by that:
with recursive entries as (
select id, parent_id, id as root_id, 1 as level
from the_table
where parent_id = 0 -- this should be IS NULL
union all
select c.id, c.parent_id, p.root_id, p.level + 1
from the_table c
join entries p on p.id = c.parent_id
)
select id, parent_id
from entries
order by root_id, level, id;
Online example: https://rextester.com/YKUJ56922
Mysql order by parent and child
Simplify your order by clause to just what you want the sort order to be:
SELECT
parent.category_id as `parent_id`,
parent.category_group as `parent_group`,
child.category_id as `child_id`
child.category_group as `child_group`
FROM mst_category AS parent
LEFT JOIN mst_category AS child
ON child.category_parent = parent.category_id
GROUP BY parent.category_id
ORDER BY parent.category_group, child.category_group
For 3 levels:
SELECT
parent.category_id as `parent_id`,
parent.category_group as `parent_group`,
child.category_id as `child_id`
child.category_group as `child_group`,
child2.category_id as `child2_id`
child2.category_group as `child2_group`
FROM mst_category AS parent
LEFT JOIN mst_category AS child
ON child.category_parent = parent.category_id
LEFT JOIN mst_category AS child2
ON child2.category_parent = child.category_id
WHERE parent.category_id = 0
GROUP BY parent.category_id, child.category_id, child2_category_id
ORDER BY parent.category_group, child.category_group, child2.category_group
SQL Order by, parent, child, and sort order
This is how I would do it, assuming the tree that the parent-child relationship represents is only two levels deep.
SELECT *
FROM
(
SELECT p.CategoryID
, p.Category_Name
, p.IsParent
, p.ParentID
, p.Active
, p.Sort_Order as Primary_Sort_Order
, NULL as Secondary_Sort_Order
FROM tbl_Category p
WHERE p.IsParent = 1
UNION
SELECT c.CategoryID
, ' - ' + c.Category_Name AS Category_Name
, c.IsParent
, c.ParentID
, c.Active
, a.Sort_Order as Primary_Sort_Order
, c.Sort_Order as Secondary_Sort_Order
FROM tbl_Category c
JOIN tbl_Category a on c.ParentID = a.CategoryID
WHERE c.IsParent = 0
AND a.IsParent = 1
) x
ORDER BY Primary_Sort_Order ASC
, (CASE WHEN Secondary_Sort_Order IS NULL THEN 0 ELSE 1 END) ASC
, Secondary_Sort_Order ASC
Primary_Sort_Order orders the parents and its children as a group first. Then within the primary group, enforce NULL values of Secondary_Sort_Order to come first, and afterwards order by regular non-NULL values of Secondary_Sort_Order.
MySQL Sorting by parents and children
Partial solution might be the following query:
SELECT t.title FROM t GROUP BY IF(parent=0,id,parent),
IF(parent=0,-1,ordering), t.title ORDER BY IF([parent]=0,
id,parent), IF(parent=0,-1,ordering);
Result is like following:
TitleC
TitleCC
TitleA
TitleAA
TitleAB
TitleAC
TitleB
TitleBA
TitleBB
To indent the header of each group, something like report in MS Access might be used.
I've prepared it in MS Access, so there may be difference slightly in MySQL syntax.
MySQL query to order by parent then child places
I think you should put one more field in your table, called level and store in it the level of the node, and then sort your query by level then by parent.
Related Topics
Arithmetic Overflow Error Converting Numeric to Data Type Numeric
Extracting the Total Number of Seconds from an Interval Data-Type
How to Compare Data Between Two Table in Different Databases Using SQL Server 2008
How to Keep Only One Row of a Table, Removing Duplicate Rows
Oracle Database Is Hanging Infinitly in Update Queries
Split Varchar into Separate Columns in Oracle
How to Get a List of All Current Temporary Tables in SQL Server
Sql: Last_Value() Returns Wrong Result (But First_Value() Works Fine)
How to Solve Ora-00911: Invalid Character Error
How to Compute Tf/Idf with SQL (Bigquery)
Combining Order by and Union in SQL Server
Using SQL Localdb in a Windows Service
Asynchronous Triggers in SQL Server 2005/2008
How to Optimize/Refactor a Tsql "Like" Clause