Sort an array so that null values always come last
Check out .sort()
and do it with custom sorting.
Example
function alphabetically(ascending) {
return function (a, b) {
// equal items sort equally
if (a === b) {
return 0;
}
// nulls sort after anything else
if (a === null) {
return 1;
}
if (b === null) {
return -1;
}
// otherwise, if we're ascending, lowest sorts first
if (ascending) {
return a < b ? -1 : 1;
}
// if descending, highest sorts first
return a < b ? 1 : -1;
};
}
var arr = [null, "a", "z", null, "b"];
console.log(arr.sort(alphabetically(true)));
console.log(arr.sort(alphabetically(false)));
Sort an array of numbers so that null values come last
You can first sort by not null
and then by numbers.
var arr = [5, 25, null, 1, null, 30]
arr.sort(function(a, b) {
return (b != null) - (a != null) || a - b;
})
console.log(arr)
Sort NULL values to the end of a table
NULL
values are sorted last in default ascending order. You don't have to do anything extra.
The issue applies to descending order, which is the perfect inverse and thus sorts NULL
values on top.
PostgreSQL 8.3 introduced NULLS LAST
:
ORDER BY somevalue DESC NULLS LAST
For PostgreSQL 8.2 and older or other RDBMS without this standard SQL feature:
ORDER BY (somevalue IS NULL), somevalue DESC
FALSE
sorts before TRUE
, so NULL
values come last, just like in the example above.
See:
- Sort by column ASC, but NULL values first?
- The manual on
SELECT
How to sort an EAV model that have null values?
Note: I'm still somewhat confused about what you want your resultset to look like.
select *
from value v1
left join value v2 on (v1.entity_id = v2.entity_id
and v2.field_id = 2)
where v1.field_id = 1 -- assuming all users have a name
order by v2.value;
Result:
ENTITY_ID | FIELD_ID | VALUE | ENTITY_ID | FIELD_ID | VALUE
----------|----------|-----------|------------------------------
1 | 1 | "Alice" | 1 | 2 | "24"
2 | 1 | "Bob" | 2 | 2 | "27"
3 | 1 | "Charlie" | null | null | null
Or if you prefer the names of the fields:
select v1.entity_id, f1.name, v1.value, f2.name, v2.value
from value v1
join field f1 on v1.field_id = f1.field_id
left join value v2 on (v1.entity_id = v2.entity_id
and v2.field_id = 2)
left join field f2 on v2.field_id = f2.field_id
where f1.name = 'firstname' -- assuming all users have a name
order by v2.value;
Result:
ENTITY_ID | NAME | VALUE | NAME | VALUE
----------|-------------|-----------|--------------
1 | "firstname" | "Alice" | "age" | "24"
2 | "firstname" | "Bob" | "age" | "27"
3 | "firstname" | "Charlie" | null | null
For the case where there's an entity, that doesn't have a firstname, I added two rows to entity and a row to value:
insert into entity values (4);
insert into entity values (5);
insert into value values (4, 2, '102');
If a record exists in the entity table, it will always be in this result:
select *
from entity e
left join value v1 on (e.entity_id = v1.entity_id
and v1.field_id = 1) -- firstname
left join value v2 on (e.entity_id = v2.entity_id
and v2.field_id = 2) -- age
-- order by v2.value IS NULL; -- age nulls last
Result:
ENTITY_ID | ENTITY_ID | FIELD_ID | VALUE | ENTITY_ID | FIELD_ID | VALUE
----------|-----------|------------|-----------|------------|----------|------
1 | 1 | 1 | "Alice" | 1 | 2 | "24"
2 | 2 | 1 | "Bob" | 2 | 2 | "27"
4 | null | null | null | 4 | 2 | "102"
3 | 3 | 1 | "Charlie" | null | null | null
5 | null | null | null | null | null | null
SQL how to make null values come last when sorting ascending
select MyDate
from MyTable
order by case when MyDate is null then 1 else 0 end, MyDate
Sort by column ASC, but NULL values first?
Postgres has the NULLS FIRST | LAST
modifiers for ORDER BY
expression:
... ORDER BY last_updated NULLS FIRST
The typical use case is with descending sort order (DESC
), which produces the complete inversion of the default ascending order (ASC
) with null values first - which is often not desirable. To sort NULL
values last:
... ORDER BY last_updated DESC NULLS LAST
To support the query with an index, make it match:
CREATE INDEX foo_idx ON tbl (last_updated DESC NULLS LAST);
Postgres can read btree indexes backwards, but for some query plans it matters where NULL
values are appended. See:
- Performance impact of view on aggregate function vs result set limiting
LINQ: Sort records in ascending order with NULL values last
You could use int.MaxValue
or something for those with NULL
:
IEnumerable<EKGTypes> items = context.EKGTypes
.ToList()
.Select(c => MapEntity(c))
.OrderBy(c =>
c.DisplayOrder.HasValue
? (c.DisplayOrder == 0 ? (int.MaxValue - 1) : c.DisplayOrder)
: int.MaxValue)
.ToList();
So you effectively sort by DisplayOrder
while the ones with DisplayOrder == null
will be treated as if their DisplayOrder
was int.MaxValue
and the ones with DisplayOrder == 0
as if their DisplayOrder
was int.MaxValue - 1
.
So at first all non-NULL and not-0 will be sorted by their DisplayOrder
, followed by the ones with 0
and finally the NULL
values.
Replace NULL values per partition
The window function first_value()
with the right ordering is probably cheapest:
SELECT session_id, step
, COALESCE(device
, first_value(device) OVER (PARTITION BY session_id ORDER BY device IS NULL, step)
) AS device
FROM tbl
ORDER BY session_id DESC, step;
db<>fiddle here
ORDER BY device IS NULL, step
sorts NULL
values last, so the earliest step
with a notnull value is picked. See:
- Sorting null values after all others, except special
If notnull devices per session_id
are always the same, you can simplify to just ORDER BY device IS NULL
. And you don't need COALESCE
.
PostgreSQL: order by column, with specific NON-NULL value LAST
Postgres allows boolean
values in the ORDER BY
clause, so here is your generalised 'X LAST'
:
ORDER BY (my_column = 'X')
The expression evaluates to boolean
, resulting values sort this way:
FALSE (0)
TRUE (1)
NULL
Since we deal with non-null values, that's all we need. Here is your one-liner:
...
ORDER BY (zone = 'Future'), zone, status;
Related:
- Sorting null values after all others, except special
- Select query but show the result from record number 3
- SQL two criteria from one group-by
Sort list while pushing None values to the end
>>> l = [1, 3, 2, 5, 4, None, 7]
>>> sorted(l, key=lambda x: (x is None, x))
[1, 2, 3, 4, 5, 7, None]
This constructs a tuple for each element in the list, if the value is None
the tuple with be (True, None)
, if the value is anything else it will be (False, x)
(where x
is the value). Since tuples are sorted item by item, this means that all non-None
elements will come first (since False < True
), and then be sorted by value.
Related Topics
Are Stored Procedures More Efficient, in General, Than Inline Statements on Modern Rdbms'S
Why Is SQL Server Throwing This Error: Cannot Insert the Value Null into Column 'Id'
Dynamic Sorting Within SQL Stored Procedures
SQL "Select Where Not in Subquery" Returns No Results
Getting Date List in a Range in Postgresql
How to Have an Indexed View in MySQL
How to Pass Parameters to a View in SQL
Left Join Turns into Inner Join
Return a Value If No Record Is Found
How to Drop SQL Default Constraint Without Knowing Its Name
Find the Smallest Unused Number in SQL Server
Permanently Set Postgresql Schema Path
Mysql: What Is a Reverse Version of Like
Extract Date (Yyyy/Mm/Dd) from a Timestamp in Postgresql