on 2020 May 13 3:15 PM
My problem is that I want to sort a list in a special way.
Exempel:
Pos Material Location Level 10 AE Pal1 1 10 AC Pal2 2 10 AD Pal3 2 10 AB Pal3 4 30 AD Pal1 1 30 AC Pal2 2 30 AB Pal3 2 30 AE Pal4 4 70 AC Pal2 1 70 AE Pal3 2 70 AD Pal4 4 70 AF Pal4 4 60 AB Pal1 1 60 AF Pal2 2 60 AD Pal3 2 60 AE Pal4 4 60 AE Pal5 4
First I want to sort Loaction asc, Material asc on Level 1. Then I want to continue sorting under the respective Pos at other levels. The sorting should be the same, Location asc, material asc.
The result should be as follows:
Pos Material Location Level 60 AB Pal1 1 60 AF Pal2 2 60 AD Pal3 2 60 AE Pal4 4 60 AE Pal5 4 30 AD Pal1 1 30 AC Pal2 2 30 AB Pal3 2 30 AE Pal4 4 10 AE Pal1 1 10 AC Pal2 2 10 AB Pal3 4 10 AD Pal3 2 70 AC Pal2 1 70 AE Pal3 2 70 AD Pal4 4 70 AF Pal4 4
I have tested different solutions, but I doesn't solve it. How on earth do I solve this?
Request clarification before answering.
While I agree that Rolle could have tried harder to clarify the specs - I don't find that too hard to solve - unless I have missed some details.
General assumption: There is one entry with level 1 for every Pos. (If not, one would have to change the CTE accordingly.)
Here you go:
drop table if exists TestPos; create table TestPos( -- add a PK column just to show how to conserve original order PK int default autoincrement primary key, Pos int not null, Material varchar(10) not null, Location varchar(10) not null, Level int not null ); -- Sample date insert TestPos(Pos, Material, Location, Level) values (10, 'AE', 'Pal1', 1), (10, 'AC', 'Pal2', 2), (10, 'AD', 'Pal3', 2), (10, 'AB', 'Pal3', 4), (30, 'AD', 'Pal1', 1), (30, 'AC', 'Pal2', 2), (30, 'AB', 'Pal3', 2), (30, 'AE', 'Pal4', 4), (70, 'AC', 'Pal2', 1), (70, 'AE', 'Pal3', 2), (70, 'AD', 'Pal4', 4), (70, 'AF', 'Pal4', 4), (60, 'AB', 'Pal1', 1), (60, 'AF', 'Pal2', 2), (60, 'AD', 'Pal3', 2), (60, 'AE', 'Pal4', 4), (60, 'AE', 'Pal5', 4); -- Check sample data with OP's input: select Pos, Material, Location, Level from TestPos order by PK; -- Use a CTE to get the order of the entries of Level 1 -- sorted by Location asc, Material asc, as was specified -- (and by Pos added by me) -- and use rank() to get a sort criterium, -- and then join the CTE with the original data on Pos -- and thereby apply the sort criterium to all entries with the same Pos, -- then sorting by the further columns with CTE_FirstLevel as (select Pos, rank() over (order by Location, Material, Pos) as Level1Order from TestPos where Level = 1) select TP.Pos, TP.Material, TP.Location, TP.Level from TestPos TP inner join CTE_FirstLevel CTE on TP.Pos = CTE.Pos order by CTE.Level1Order, TP.Location, TP.Material, TP.Level;
As said, I don't think it's that difficult or "something that should be done outside the database"... YMMV.
I would even state that it is a not too rare requirement - in my humble experience at least - to sort some result set based on a criterium not directly shown in the output.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I am afraid that you have done his job, while he was sleeping. I don’t know how much time you have spent to find, write and test the solution.
I am not against solving everything in SQL. Sometimes it is a good exercise for a brain, but not when the final solution becomes non-maintainable anymore. For example, application servers are easy to debug and scale-up, when you have more active users, and the database resources can be used for something important (such as analytics).
I don’t know how much time you have spent to find, write and test the solution.
Well, say, around 10 minutes? - When answering, I'm usually trying to combine "being helpful" with "learning for myself", and that was particularly the case here. Of course that may conflict now and then with "doing other's homework." but here I was more interested in checking whether the comments like "not possible in one query" were valid or not...
And to be clear: Contributors like the SQL Anywhere engineers, Breck and myself are apparently mainly focussed on SQL-based solutions. I'm well aware that you, Vlad, often point to different solutions outside SQL databases, and IMHO this is very often a helpful perspective. So please keep on providing those insights!
Thanks for your comment. On my daily basis I work with people, who built their solutions using different technologies, and quite often I see long-running tasks (e.g. web requests, that fetch data from a database) that use these kind-of-queries with many tables/joins etc. And these queries cause 90% CPU time of the DB server that can be avoided if people just change their architecture & development a bit. You can create indexes, tune hints until a certain point, after that you should better give us and say something like: "maybe we can store these records into Redis and free 70% of the CPU Time?"
Something like that...
"not possible in one query" was never claimed. It is true that there is no single multi-column sort of the provided data that can produce the desired results. It requires at two separate sorts and one will generate a mapping to create an ordinal for the 'pos' column of the final sort based on other values in the table. You've generated that mapping and used it via a join with some nice SQL wizardry.
In this SQL query, I suspect that if you are missing a 'level 1' row for a given location & material then the whole section for that 'pos' value will not be reported. And if there are multiple level-1 rows, then 'pos' sections will get repeated (once for each level-1 value). Correct?
Oops, I apparently misunderstood your statement "I don't think it can be done in a single sort."...
Yes, as stated, the assumption I took from the OP was that there is exactly one entry with Level 1 per Pos value, and there are no entries with "overlapping" sort values. But if this is not true, then I still think the basic query pattern can be adjusted, say to use "Min(Level)" instead of Level 1 within the CTE or to use row_number() instead of rank(). - In order to "not do too much homework", I'd say the rest is left as an exercise for the reader... 🙂
User | Count |
---|---|
76 | |
30 | |
10 | |
8 | |
8 | |
7 | |
7 | |
5 | |
4 | |
4 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.