SQL MIN нескольких столбцов обрабатывает нулевые значения

Я пытаюсь использовать агрегатную функцию MIN() и получить минимальную дату из двух столбцов, и мне удалось написать для этого SQL-запрос. Но если один из столбцов имеет значения NULL, мой запрос ниже принимает дату по умолчанию как «1900-01-01T00:00:00Z». Он должен брать дату либо из столбца 1, либо из столбца 2, в зависимости от того, какое значение имеет значение.

Вот схема и данные SQLFiddle.

+----+--------------+---------------+
| ID | ObservedDate | SubmittedDate |
+----+--------------+---------------+
|  1 | '2017-02-14' | '2017-02-15'  |
|  1 | '2017-01-21' | '2017-01-22'  |
|  2 | '2017-01-21' |               |
+----+--------------+---------------+

Запрос

SELECT [ID],
        CASE WHEN MIN(ObservedDate)<=MIN(SubmittedDate) 
             THEN COALESCE(MIN(ObservedDate),MIN(SubmittedDate))
        ELSE COALESCE(MIN(SubmittedDate),MIN(ObservedDate)) end as RiskReferenceDate
FROM Measurements
group by ID

Причина, по которой я использовал COALESCE, заключается в том, что я хочу, чтобы мой запрос учитывал данные из столбца со значением и игнорировал столбец с нулевым значением.

Ожидаемый результат

+----+-------------------+
| ID | RiskReferenceDate |
+----+-------------------+
|  1 | '2017-01-21'      |
|  2 | '2017-01-21'      |
+----+-------------------+

person shockwave    schedule 13.03.2018    source источник
comment
В вашей Sql Fiddle вместо '' вы ставите NULL (2, '2017-01-21 00:00:00', null)   -  person Joe Taras    schedule 13.03.2018
comment
Желаемый результат противоречит тому, что вы говорите. Вы говорите, что хотите MIN, но желаемый результат - MAX. И '' ‹› NULL. Когда у вас есть пустая строка в качестве даты, она неявно преобразуется в 1900-01-01.   -  person Sean Lange    schedule 13.03.2018
comment
Извините, я обновил желаемый результат   -  person shockwave    schedule 13.03.2018


Ответы (2)


Ваша проблема не в NULL значениях. Ваша проблема - пустые строки. Это вставляется как дата 0.

Самое простое решение — исправить код так, чтобы он вставлял правильное значение, как показано в этом SQL Fiddle.

Вы можете применить это, добавив контрольное ограничение:

alter table Measurements add constraint chk_measurements_ObservedDate check (ObservedDate > '2000-01-01');  -- or whatever date

alter table Measurements add constraint chk_measurements_SubmittedDate check (SubmittedDate > '2000-01-01');  -- or whatever date

Если у вас есть существующие данные в таблице, вы можете сделать:

update Measurements
    set ObservedDate = NULLIF(ObservedDate, 0),
        SubmittedDate = NULLIF(SubmittedDate, 0)
    where ObservedDate = 0 or SubmittedDate = 0;

Вы можете исправить это на месте, немного усложнив запрос:

SELECT [ID],
       (CASE WHEN MIN(NULLIF(ObservedDate, 0)) <= MIN(NULLIF(SubmittedDate, 0)) 
             THEN COALESCE(MIN(NULLIF(ObservedDate, 0)), MIN(NULLIF(SubmittedDate, 0)))
             ELSE COALESCE(MIN(NULLIF(SubmittedDate, 0)), MIN(NULLIF(ObservedDate, 0)))
        END) as RiskReferenceDate
FROM Measurements
GROUP BY ID;

Но я настоятельно призываю вас исправить данные.

person Gordon Linoff    schedule 13.03.2018

Я думаю, что проблема вызвана пустой строкой, которую вы вставили в один из столбцов даты, вы действительно должны это исправить.

Во всяком случае, это, кажется, работает:

with a as (
  select   ObservedDate Dt
  from     Measurements
  where ObservedDate <> ''
  union all
  select   SubmittedDate
  from     Measurements
  where SubmittedDate <> ''
)
select min(Dt)
from a
person MJH    schedule 13.03.2018