What about doing a little math against your ID column to dynamically generate the group?
SELECT grp, FLOOR(id/10) AS id_grp
FROM animals
GROUP BY grp, id_grp
This would give you groups of 10 based on the ID of the record. I used your animals table above to generate the data below.
Sample data
INSERT INTO animals VALUES
('mammal',10,'dog'),('mammal',11,'dog'),('mammal',12,'dog'),
('mammal',21,'cat'),('mammal',22,'cat'),('mammal',23,'cat'),
('mammal',24,'cat'),('mammal',25,'cat'),('mammal',26,'cat'),
('bird',30,'penguin'),('bird',31,'penguin'),('bird',32,'penguin'),
('bird',33,'penguin'),('fish',44,'lax'),('fish',45,'lax'),
('fish',46,'lax'),('fish',47,'lax'),('fish',48,'lax'),
('mammal',31,'whale'),*'fish',51,'lax'),('fish',52,'lax'),
('fish',53,'lax'),('fish',54,'lax'),('bird',10,'ostrich');
Query Output
+--------+--------+
| grp | id_grp |
+--------+--------+
| fish | 4 |
| fish | 5 |
| mammal | 1 |
| mammal | 2 |
| mammal | 3 |
| bird | 1 |
| bird | 3 |
+--------+--------+
7 rows in set (0.00 sec)
From what you're describing, it doesn't sound like anything is contraindicated related to the C collation order. In fact, Robert Haas, has a great discussion on the subject here, which seems to come to the conclusion that if you don't need locale aware sorting, just don't use it: Perils of Collation Aware Comparisons
I did notice you are on Debian Wheezy. The stock kernel for Debian Wheezy is 3.2, which if you're using that, has abysmal performance on database workloads. I would investigate that along with the collation testing, if you are not happy with the performance of your machine.
The wheezy-backports kernel is 3.16, which does not have these issues. Discussion and performance tests are here: Benchmarking PostgreSQL with Different Kernel Versions
Hope that helps. =)
Best Answer
You can use a CASE expression for the ORDER BY: