How to Order by Column with Non-Null Values First in Sql

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

SQL Find the first non null value with arbitrary order by

Just do :

SELECT TOP 1 Value
FROM mytable
WHERE Value IS NOT NULL
ORDER BY ID

To get the last not null value switch the ordering:

ORDER BY ID DESC

To expand the same logic to a greater number of columns you can use the following query:

SELECT (SELECT TOP 1 Value1 FROM mytable 
WHERE Value1 IS NOT NULL ORDER BY ID) AS min_Value1,
(SELECT TOP 1 Value2 FROM mytable
WHERE Value2 IS NOT NULL ORDER BY ID) AS min_Value2

Demo here

How to order by column with non-null values first in sql

See Sort Values Ascending But NULLS Last

basically

SELECT *
FROM @Temp
ORDER BY CASE WHEN LastName IS NULL THEN 1 ELSE 0 END, LastName

How to get the first non-NULL value in SQL?

You can put that CASE in the ORDER BY of the FIRST_VALUE.

Then the null's will be sorted last for that function.

create table test
(
pid int,
pdate date,
BMI decimal(4,1)
)

insert into test (pid, pdate, BMI) values
(1, '2000-01-01', NULL)
, (1, '2003-05-01', 18.5)
, (1, '2002-07-15', 24.9)
, (2, '2009-09-25', NULL)
, (2, '2015-04-18', 21.7)
;
select *
, first_value(BMI) over (partition by pid order by case when BMI is not null then 1 else 2 end, date(pdate)) as firstBMI
from test
order by pid, pdate

pid | pdate | BMI | firstBMI
:-- | :--------- | :--- | :-------
1 | 2000-01-01 | null | 24.9
1 | 2002-07-15 | 24.9 | 24.9
1 | 2003-05-01 | 18.5 | 24.9
2 | 2009-09-25 | null | 21.7
2 | 2015-04-18 | 21.7 | 21.7

db<>fiddle here

Finding the first non-null in a partition

We could try the following approach. Here we are applying ROW_NUMBER with a partition on person and also a partition on whether or not the marital status value is NULL. We then use the most recent non NULL marital status value, per person, to fill in any NULL missing marital status values.

WITH cte AS (
SELECT *, ROW_NUMBER() OVER (
PARTITION BY Person,
CASE WHEN MaritalStatus IS NULL THEN 0 ELSE 1 END
ORDER BY Year DESC) rn
FROM mytable
)

SELECT t1.Person, t1.Year, COALESCE(t1.MaritalStatus, t2.MaritalStatus) AS MaritalStatus
FROM mytable t1
LEFT JOIN cte t2
ON t2.Person = t1.Person AND
t2.MaritalStatus IS NOT NULL AND
t2.rn = 1;

screen capture from demo link below

Demo

Fastest way to get the first non null value of a column with in a range of dates in SQL SERVER

I assume you want to order the dates. Otherwise, you will not be able to find the first not null foo value. Because, the term first is relative. You need to have a order by clause to find the first not null value.

I have given sample code for your reference.

CREATE TABLE #test (datevalue DATE, foo INT);

CREATE CLUSTERED INDEX cix_test ON #test (datevalue);

INSERT INTO #test
VALUES ('20181001', NULL), ('20181101', 10), ('20181201', NULL), ('20190101', 1);

SELECT TOP 1 FIRST_VALUE(foo) OVER (
ORDER BY datevalue
)
FROM #test
WHERE datevalue BETWEEN '20181001'
AND '20181101'
AND foo IS NOT NULL;

Ordering within group and selecting non-null values

You may use match_recognize to capture rows with non-null values and reference them in a measures clause:

select x, y, z
from test_tab
match_recognize (
partition by x
order by z asc nulls last
measures
/*The first value of Z (nulls last)*/
first(any_.z) as z,
/*The first non-null value of Y:
captured either by any_ pattern
or by other that skips all nulls first
*/
coalesce(first(any_.y), first(other.y)) as y
/*Any row
followed by zero or more Y with null
followed by any number of any non-null Y rows for the same X
*/
pattern (any_ y_null* other*)
define
y_null as y is null
)

Or from Oracle 21c you may reuse window specification by declaring it at the bottom of select statement and use your original approach:

select distinct
x,
first_value(y ignore nulls) over fv as y,
first_value(z ignore nulls) over fv as z
from test_tab
window fv as (
partition by x
order by z asc nulls last
rows between unbounded preceding and unbounded following
)

Given this sample data:

create table test_tab(X, Y, Z) as
select 'a', 'a0', NULL from dual union all
select 'a', NULL, 1 from dual union all
select 'a', 'a2', 2 from dual union all
select 'b', 'b1', 1 from dual union all
select 'b', 'b2', 2 from dual

both the queries return this result:



Leave a reply



Submit