Reputation: 2152
Consider the table below: (here's a db-fiddle with this example)
id primary_sort record_id record_sort alt_sort
1 2 1 11 100
2 2 2 10 101
3 3 1 12 108
4 3 1 13 107
5 3 2 14 105
6 1 2 15 109
I'd like to sort this according to primary_sort
first. If equal, the next sort field depends on the value of record_id
: if two rows has the same record_id
, then sort them by record_sort
. Otherwise, sort them by alt_sort
.
I think the query should look something like this:
select * from example
order by
primary_sort,
case
when [this_row].record_id = [other_row].record_id
then record_sort
else alt_sort
end
;
Expected output:
id primary_sort record_id record_sort alt_sort
6 1 2 15 109
1 2 1 11 100
2 2 2 10 101
5 3 2 14 105
3 3 1 12 108
4 3 1 13 107
Here's some pseudocode in Java, showing my intent:
int compareTo(Example other) {
if (this.primary_sort != other.primary_sort)
{
return this.primary_sort.compareTo(other.primary_sort);
}
else if (this.record_id == other.record_id)
{
return this.record_sort.compareTo(other.record_sort);
}
else
{
return this.alt_sort.compareTo(other.alt_sort);
}
}
(this is a minimal, reproducible example. Similar SO questions I've found on conditional order by
are not applicable, because my condition is based on values in both rows (i.e. [this_row].record_id = [other_row].record_id
))
Upvotes: 0
Views: 215
Reputation: 35930
You can use the analytical function as follows:
select * from example
order by primary_sort,
case when count(*) over (partition by primary_sort, record_id) > 1
then record_sort else record_id end, alt_sort;
Upvotes: 1
Reputation: 1271171
You can do what you describe using window functions. Something like this:
select *
from example e
order by primary_sort,
(case when count(*) over (partition by primary_sort, record_id) > 1 then record_sort
end) nulls last,
alt_sort;
This does not return the results you specify. But some variation is probably what you intend.
Upvotes: 1