Database Administrators
Q&A for database professionals who wish to improve their database skills
Latest Questions
11
votes
2
answers
11153
views
ORDER BY and comparison of mixed strings of letters and numbers
We need to do some reporting on values that are usually mixed strings of numbers and letters that need to be sorted 'naturally'. Things like, e.g. "P7B18" or "P12B3". @The strings will mostly be sequences of letters then numbers alternating. The number of these segments and the length of each could...
We need to do some reporting on values that are usually mixed strings of numbers and letters that need to be sorted 'naturally'. Things like, e.g. "P7B18" or "P12B3". @The strings will mostly be sequences of letters then numbers alternating. The number of these segments and the length of each could vary, though.
We'd like the numeric portions of these to be sorted in numeric order. Obviously, if I just handle those string values directly with
ORDER BY
, then "P12B3" is going to come before "P7B18", since "P1" is earlier than "P7", but I'd like the reverse, as "P7" naturally precedes "P12".
I'd also like to be able to do range comparisons, e.g. @bin < 'P13S6'
or some such. I don't have to handle floating point or negative numbers; these will strictly be non-negative integers that we're dealing with. String lengths and number of segments could potentially be arbitrary, with no fixed upper bounds.
In our case, string casing isn't important, though if there's a way to do this in a collation-aware fashion, others might find that useful. The ugliest part of all this is I'd like to be able to do both ordering, and range filtering in the WHERE
clause.
If I were doing this in C#, it would be a pretty simple task: do some parsing to separate the alpha from the numeric, implement IComparable, and you're basically done. SQL Server, of course, doesn't appear to offer any similar functionality, at least as far as I'm aware.
Anybody know any good tricks to make this work? Is there some little-publicized ability to create custom CLR types that implement IComparable and have this behave as expected? I'm also not opposed to Stupid XML Tricks (see also: list concatenation), and I've got CLR regex matching/extracting/replacement wrapper functions available on the server as well.
**EDIT:**
As a slightly more detailed example, I'd want the data to behave something like this.
SELECT bin FROM bins ORDER BY bin
bin
--------------------
M7R16L
P8RF6JJ
P16B5
PR7S19
PR7S19L
S2F3
S12F0
i.e. break the strings into tokens of all letters or all numbers, and sort them either alphabetically or numerically respectively, with the leftmost tokens being the most significant sorting term. Like I mentioned, piece of cake in .NET if you implement IComparable, but I don't know how (or if) you can do that sort of thing in SQL Server. It's certainly not something I've ever come across in 10 or so years of working with it.
db2
(9708 rep)
Jan 20, 2016, 02:28 PM
• Last activity: May 17, 2025, 04:01 AM
15
votes
4
answers
4954
views
Is there a collation to sort the following strings in the following order 1,2,3,6,10,10A,10B,11?
I have a database with a VARCHAR column that contains integers of varying length. I want to sort them so 10 comes after 9, not 1, and 70A comes after 70. I was able do this with [PATINDEX()](http://msdn.microsoft.com/en-us/library/ms188395.aspx), a CTE, and CASE statements in the WHERE clause. Howev...
I have a database with a VARCHAR column that contains integers of varying length. I want to sort them so 10 comes after 9, not 1, and 70A comes after 70. I was able do this with [PATINDEX()](http://msdn.microsoft.com/en-us/library/ms188395.aspx) , a CTE, and CASE statements in the WHERE clause.
However, I was wondering if there was a collation where this would be unecessary.
Justin Dearing
(2727 rep)
Jul 13, 2011, 05:15 PM
• Last activity: Dec 15, 2022, 01:33 AM
29
votes
3
answers
20319
views
How to ORDER BY typical software release versions like X.Y.Z?
Given a "SoftwareReleases" table: | id | version | | 1 | 0.9 | | 2 | 1.0 | | 3 | 0.9.1 | | 4 | 1.1 | | 5 | 0.9.9 | | 6 | 0.9.10 | How do I produce this output? | id | version | | 1 | 0.9 | | 3 | 0.9.1 | | 5 | 0.9.9 | | 6 | 0.9.10 | | 2 | 1.0 | | 4 | 1.1 |
Given a "SoftwareReleases" table:
| id | version |
| 1 | 0.9 |
| 2 | 1.0 |
| 3 | 0.9.1 |
| 4 | 1.1 |
| 5 | 0.9.9 |
| 6 | 0.9.10 |
How do I produce this output?
| id | version |
| 1 | 0.9 |
| 3 | 0.9.1 |
| 5 | 0.9.9 |
| 6 | 0.9.10 |
| 2 | 1.0 |
| 4 | 1.1 |
Chris Betti
(487 rep)
Aug 18, 2014, 05:46 PM
• Last activity: Jul 7, 2021, 02:42 PM
20
votes
3
answers
12979
views
How to treat numbers within strings as numbers when sorting ("A3" sorts before "A10", not after)
For all of these queries: SELECT label FROM personal.storage_disks ORDER BY label ASC; SELECT label FROM personal.storage_disks ORDER BY label COLLATE "C" ASC; SELECT label FROM personal.storage_disks ORDER BY label COLLATE "POSIX" ASC; SELECT label FROM personal.storage_disks ORDER BY label COLLATE...
For all of these queries:
SELECT label FROM personal.storage_disks ORDER BY label ASC;
SELECT label FROM personal.storage_disks ORDER BY label COLLATE "C" ASC;
SELECT label FROM personal.storage_disks ORDER BY label COLLATE "POSIX" ASC;
SELECT label FROM personal.storage_disks ORDER BY label COLLATE "default" ASC;
The output is always:
DISK 1, DISK 10, DISK 2, DISK 3, [...]
But, I want and expect: DISK 1, DISK 2, DISK 3, [...] DISK 10
I'm out of collations to try now according to SELECT * FROM pg_collation;
... unless I'm supposed to use one of the many really weird ones with cryptic names. (I even tried a bunch of those with the same result.)
Please note that I've read the existing seemingly related SE questions as well as many articles on SORT BY
, but they didn't help and didn't clear up anything for me.
I'm using PostgreSQL 12.4
user15080516
(745 rep)
Feb 11, 2021, 01:47 PM
• Last activity: Feb 19, 2021, 07:14 PM
2
votes
3
answers
2586
views
Sort varchar by its numeric fields
*I'm sure this has been asked before, but since the question can be formulated in many different ways it's difficult to find the proper answer.* I have an **orders** table with a *varchar* field for the order **number**, which is formatted with 4-digits year, a dash (-), and a progressive numeric va...
*I'm sure this has been asked before, but since the question can be formulated in many different ways it's difficult to find the proper answer.*
I have an **orders** table with a *varchar* field for the order **number**, which is formatted with 4-digits year, a dash (-), and a progressive numeric value. For example it may contain the following values:
`
SELECT number FROM orders ORDER BY number LIMIT 10;
`
number
----------
1999-13
2019-11
2020-1
2020-10
2020-100
2020-12
2020-2
2020-21
2020-3
2021-1
I need to sort that field by year and then by the progressive number, with this expected result:
number
----------
1999-13
2019-11
2020-1
2020-2
2020-3
2020-10
2020-12
2020-21
2020-100
2021-1
A DB fiddle is here .
My questions are:
1) Which is the simplest way to achieve this with an ORDER subclause?
2) How to add an efficient index using this custom sort without having to modify the table?
I would like to keep at least the first answer as database-agnostic as possible (that's why I haven't included db specific tags), but if different best answers are possible for different DBMS/versions, let's assume PostgreSQL 12.
Claudio Floreani
(102 rep)
Nov 20, 2020, 12:15 PM
• Last activity: Nov 20, 2020, 02:45 PM
12
votes
2
answers
9680
views
Why does Postgres ORDER BY seem to halfway ignore leading underscores?
I have an `animal` table with a `name` `varchar(255)`, and I've added rows with the following values: Piranha __Starts With 2 Rhino Starts With 1 0_Zebra _Starts With 1 Antelope _Starts With 1 When I run this query: zoology=# SELECT name FROM animal ORDER BY name; name ----------------- 0_Zebra Ante...
I have an
animal
table with a name
varchar(255)
, and I've added rows with the following values:
Piranha
__Starts With 2
Rhino
Starts With 1
0_Zebra
_Starts With 1
Antelope
_Starts With 1
When I run this query:
zoology=# SELECT name FROM animal ORDER BY name;
name
-----------------
0_Zebra
Antelope
Piranha
Rhino
_Starts With 1
_Starts With 1
Starts With 1
__Starts With 2
(8 rows)
Notice how the rows are sorted in an order that implies the leading _
is used to place the _Starts With 1
rows before the Starts
row, but the __
in the __Starts With 2
seems to ignore this fact, as if the 2
at the end is more important than the first two characters.
Why is this?
If I sort with Python, the result is:
In : for animal in sorted(animals):
....: print animal
....:
0_Zebra
Antelope
Piranha
Rhino
Starts With 1
_Starts With 1
_Starts With 1
__Starts With 2
Furthermore, Python ordering suggests that underscores come *after* letters, which indicates that the Postgres's sorting of the first two _Starts
rows before the Starts
row is incorrect.
Note: I'm using Postgres 9.1.15
Here are my attempts at finding the collation:
zoology=# select datname, datcollate from pg_database;
datname | datcollate
-----------+-------------
template0 | en_US.UTF-8
postgres | en_US.UTF-8
template1 | en_US.UTF-8
zoology | en_US.UTF-8
(4 rows)
And:
zoology=# select table_schema,
table_name,
column_name,
collation_name
from information_schema.columns
where collation_name is not null
order by table_schema,
table_name,
ordinal_position;
table_schema | table_name | column_name | collation_name
--------------+------------+-------------+----------------
(0 rows)
orokusaki
(1209 rep)
Sep 17, 2015, 02:55 PM
• Last activity: Jul 6, 2019, 12:23 PM
2
votes
3
answers
8725
views
Sorting by month by chronological occurrence when the year doesn't matter?
Given a table with a date column, and given a query that selects dates in a given range of the year (like "November 20th through February 20th"), and where the year portion of the date doesn't matter (such as upcoming birthdays), how can the results be sorted by month in the correct chronological or...
Given a table with a date column, and given a query that selects dates in a given range of the year (like "November 20th through February 20th"), and where the year portion of the date doesn't matter (such as upcoming birthdays), how can the results be sorted by month in the correct chronological order for the selected time range?
For example, if the query grabs all dates between November 20th and February 20th regardless of year, it should sort them in the order:
Nov -> Dec -> Jan -> Feb
But a regular sort by month actually produces:
Jan -> Feb -> Nov -> Dec
Or an inverted sort produces:
Dec -> Nov -> Feb -> Jan
both of which are wrong.
Here's a sample query with a three day range at the end of the year:
SELECT EventDate
FROM Events
WHERE TIMESTAMPDIFF(YEAR, EventDate, "2012-12-28" + INTERVAL 3 DAY)
> TIMESTAMPDIFF(YEAR, EventDate, "2012-12-28" - INTERVAL 1 DAY)
ORDER BY DATE_FORMAT(EventDate, "%m-%d") DESC
It produces:
2012-01-01
2008-01-01
2008-01-01
1987-01-02
1994-12-28
Where it should produce:
1994-12-28
2012-01-01
2008-01-01
2008-01-01
1987-01-02
Is there a way to get it to sort by month and day in a "going forward from range start" order?
I searched here and on SO but didn't find an answer that dealt with both year end wrapping of months and a scenario where the year in the date field isn't relevant for sorting.
**Update**: The range should always sort forward, so if the range is Feb to Nov, it does a standard sort of
Feb - > Mar -> Apr ...
. If the range is Nov to Feb, it sorts Nov -> Dec -> Jan ...
.
Although I don't anticipate that being an issue since I don't need to query more than a 3 month window.
Nick
(301 rep)
May 30, 2016, 11:59 AM
• Last activity: Jun 21, 2019, 04:20 PM
0
votes
1
answers
4388
views
postgresql - trouble to order a list obtained by string_agg
I obtained a list of numbers (and text) by a string_agg. For instance, that : "09,12,20,200,217,400,500,90,91,92,Exp3" This is the string_agg: string_agg(DISTINCT t_ligne.ligne_code::text, ','::text ORDER BY (t_ligne.ligne_code::text)) AS lignes My trouble with the ordering: I need an alphanumeric o...
I obtained a list of numbers (and text) by a string_agg.
For instance, that :
"09,12,20,200,217,400,500,90,91,92,Exp3"
This is the string_agg:
string_agg(DISTINCT t_ligne.ligne_code::text, ','::text ORDER BY (t_ligne.ligne_code::text)) AS lignes
My trouble with the ordering: I need an alphanumeric order like:
"09,12,20,90,91,92,200,217,400,500,Exp3"
If I try a CAST, it refuses to accept text "numbers" like "Exp3".
So I didn't find any way to order it like values with text objects at the end.
EDIT
I don't know how to use WITH in my query without cutting my results!
In fact, this is the total query:
SELECT l_arret_ligne.idap,
t_arret.nom_arret AS nom,
string_agg(DISTINCT t_ligne.ligne_code::text, ','::text ORDER BY (t_ligne.ligne_code::text)) AS lignes
FROM l_arret_ligne,
t_ligne,
t_arret
WHERE l_arret_ligne.id_ligne::text = t_ligne.id_ligne::text
AND l_arret_ligne.idap::text = t_arret.idap::text
AND t_ligne.ligne_type::text 'Scolaire'::text
GROUP BY l_arret_ligne.idap, t_arret.nom_arret
As my string_agg is inside a global query, I don't understand how it would be possible to cut it with WITH and globalize it at the end.
Maybe do I understand bad...
Thanks again!
EDIT 2:
Hello again!
I found one very good solution to order my results:
SELECT string_agg("rla"."t_ligne_19032019"."ligne_code", ',' ORDER BY case when (UPPER(ligne_code)=LOWER(ligne_code))=true then substring(concat('000000000000000',ligne_code),length(ligne_code)+1,15) else ligne_code end) AS lignes
FROM "rla"."t_ligne_19032019"
It works very well. BUT always the same trouble with DISTINCT!
If I add DISTINCT in the string_agg, same message:
> ERROR: in an aggregate with DISTINCT, ORDER BY expressions must
> appear in argument list
Any solution? Any advice?
Thanks again!
Cyril
Cy's
(1 rep)
Mar 15, 2019, 08:35 AM
• Last activity: Mar 26, 2019, 01:31 PM
5
votes
2
answers
3953
views
Oracle sort order changed
We recently deployed a new environment with a newer version of Oracle (12c) instead of 11r2. Only recently I noticed my data returned is sorted differently. Instead of having small letters, capital letters and numbers... (on Oracle 11r2) I get my data sorted the opposite way: numbers, capital letter...
We recently deployed a new environment with a newer version of Oracle (12c) instead of 11r2.
Only recently I noticed my data returned is sorted differently.
Instead of having small letters, capital letters and numbers... (on Oracle 11r2)
I get my data sorted the opposite way:
numbers, capital letters, small letters (Oracle 12c)
This is realy confusing the end-user of various applications querying the database. What settings do I need to check/compare to fix this problem in Oracle 12c?
The queries I refer to have an order by clause.
**EDIT**
The settings on for these parameters are the same on both evironments:
**NLS_SORT**
type: string
value:
**nls_language**
type: string
value: DUTCH
So there is no value for NLS_SORT, what is the default then?
@phil
select * from NLS_INSTANCE_PARAMETERS;
Parameter Oracle11r2 Oracle12c
NLS_LANGUAGE DUTCH DUTCH
NLS_TERRITORY THE NETHERLANDS THE NETHERLANDS
NLS_SORT
NLS_DATE_LANGUAGE
NLS_DATE_FORMAT
NLS_CURRENCY
NLS_NUMERIC_CHARACTERS
NLS_ISO_CURRENCY
NLS_CALENDAR
NLS_TIME_FORMAT
NLS_TIMESTAMP_FORMAT
NLS_TIME_TZ_FORMAT
NLS_TIMESTAMP_TZ_FORMAT
NLS_DUAL_CURRENCY
NLS_COMP BINARY BINARY
NLS_LENGTH_SEMANTICS BYTE CHAR
NLS_NCHAR_CONV_EXCP FALSE FALSE
select * from NLS_SESSION_PARAMETERS;
these are the same as my NLS settings in Oracle SQL developer, so not very relevant I guess...
select * from NLS_DATABASE_PARAMETERS;
These are the same, only NLS_RDBMS_VERSION differs
So only NLS_LENGTH_SEMANTICS differs. Is there a way to check the values for other sessions?
Jeroen
(275 rep)
Jan 5, 2016, 04:20 PM
• Last activity: Jan 6, 2016, 12:10 PM
7
votes
1
answers
24945
views
Order by alphabet and then by numbers
I have records like A5 A4 Z1 B2 C7 C1A C11A B1 B4 I want them to be sorted in this manner A4 A5 B1 B2 B4 C1 C11A C7 Z1 using the `ORDER BY` clause. I want them to be sorted by alphabets and then by numeric values.
I have records like
A5
A4
Z1
B2
C7
C1A
C11A
B1
B4
I want them to be sorted in this manner
A4
A5
B1
B2
B4
C1
C11A
C7
Z1
using the
ORDER BY
clause.
I want them to be sorted by alphabets and then by numeric values.
Abhishek
(245 rep)
Oct 31, 2013, 08:29 AM
• Last activity: Mar 5, 2015, 08:58 PM
Showing page 1 of 10 total questions