-1

I have following MySQL db table filled with data:

|id|parentId|position
|20|NULL    |1
|21|NULL    |2
|22|NULL    |3
|23|21      |1
|24|21      |2

As you may notice, position inside parent starts from 1 as well.

So if I query table:

SELECT * FROM myTable ORDER BY IFNULL(parentId, id), parentId, position

I get following results:

|id|parentId|position
|20|NULL    |1
|21|NULL    |2
|23|21      |1
|24|21      |2
|22|NULL    |3

What is actually fine, until I change the row(id#21) position to value 3,and row#22 position to value 2. Now I would like to expect following results:

|id|parentId|position
|20|NULL    |1
|22|NULL    |2
|21|NULL    |3
|23|21      |1
|24|21      |2

Unfortunately nothing changes and I have the same order:

|id|parentId|position
|20|NULL    |1
|21|NULL    |2
|23|21      |1
|24|21      |2
|22|NULL    |3

So any ideas how to change query to get wanted results?

3
  • What is the logic behind your expected result? Commented Feb 27, 2018 at 14:53
  • Possible duplicate of Mysql complex sorting by multiple columns Commented Feb 27, 2018 at 14:54
  • You just posted the same question like 3 hours ago ... if the answer doesn't suit your request just edit the question, don't post another one Commented Feb 27, 2018 at 15:06

3 Answers 3

2

I would suggest to perform an outer join to find the parent record, and then use its position to calculate an order:

SELECT    a.*
FROM      myTable a
LEFT JOIN myTable b ON a.parentId = b.id
ORDER BY  IFNULL(b.position, a.position), 
          IF(b.position, a.position, null);

When you have "grandchildren" in your table, you will need to extend this pattern:

SELECT    a.*
FROM      myTable a
LEFT JOIN myTable b ON a.parentId = b.id
LEFT JOIN myTable c ON b.parentId = c.id
ORDER BY  COALESCE(c.position, b.position, a.position), 
          IF(c.position, b.position, IF(b.position, a.position, null)), 
          IF(c.position, a.position, null);

When there can be grand-grandchildren, then:

SELECT    a.*
FROM      myTable a
LEFT JOIN myTable b ON a.parentId = b.id
LEFT JOIN myTable c ON b.parentId = c.id
LEFT JOIN myTable d ON c.parentId = d.id
ORDER BY  COALESCE(d.position, c.position, b.position, a.position), 
          IF(d.position, c.position, IF(c.position, b.position, IF(b.position, a.position, null))), 
          IF(d.position, b.position, IF(c.position, a.position, null)), 
          IF(d.position, a.position, null);

... etc, you'll get the pattern. BTW, it does not hurt to foresee more levels than needed. This last query will also return the correct result when you only have direct children, like in your sample data.

Sign up to request clarification or add additional context in comments.

Comments

0

With your expected result

SELECT * FROM myTable ORDER BY parentId, id , position

Else you can use COALESCE :

SELECT * FROM myTable
ORDER BY FIELD(COALESCE(parentId,'0'),id, position

Comments

0

It is not super clear, but this gives you what you expect

SELECT * FROM myTable ORDER BY parentId, position, IFNULL(parentId, id);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.