【问题标题】:SQL MIN of multiple columns handle null values多列的 SQL MIN 处理空值
【发布时间】:2018-03-13 15:18:29
【问题描述】:

我正在尝试使用 MIN() 聚合函数并从两列中获取最小日期,并且我能够为此编写 SQL 查询。但是,如果其中一列具有 NULL 值,则下面的查询将默认日期设为“1900-01-01T00:00:00Z”。它应该从 Column1 或 Column2 中获取日期,以具有值的为准。

这是架构和数据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'      |
+----+-------------------+

【问题讨论】:

  • 在你的 Sql Fiddle 而不是 '' 你放 NULL (2, '2017-01-21 00:00:00', null)
  • 您想要的输出与您所说的冲突。你说你想要 MIN 但你想要的输出是 MAX。和'' NULL。当您有一个空字符串作为日期时,它会隐式转换为 1900-01-01。
  • 很抱歉我更新了想要的结果

标签: sql sql-server aggregate-functions coalesce isnull


【解决方案1】:

您的问题不是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;

但我强烈建议您修复数据。

【讨论】:

    【解决方案2】:

    我认为问题是由您插入其中一个日期列的空字符串引起的,您应该真正解决这个问题。

    无论如何,这似乎有效:

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

    【讨论】:

      猜你喜欢
      • 2012-10-29
      • 2018-04-22
      • 1970-01-01
      • 2021-07-19
      • 1970-01-01
      • 2020-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多