代码之家  ›  专栏  ›  技术社区  ›  user1589188

SQL按任意顺序查找第一个非空值

  •  5
  • user1589188  · 技术社区  · 7 年前

    ID | Value
    ----------
     1 | NULL
     2 |  B
     3 |  C
     4 | NULL
    

    我想根据不同的顺序从值列中获取第一个非空值,例如:

    SELECT FIRST_NON_NULL(Value ORDER BY ID) FROM MY_TABLE
    

    这将返回B

    SELECT FIRST_NON_NULL(Value ORDER BY ID DESC) FROM MY_TABLE
    

    这将返回C

    P、 S不一定是一个值函数,只需要SELECT语句。非常感谢。


    编辑:想看看是否可以有一个可扩展的版本。

    ID | Value1 | Value2
    --------------------
     1 |  NULL  |   AA
     2 |   B    |  NULL
     3 |   C    |   CC
     4 |  NULL  |  NULL
    
    SELECT FIRST_NON_NULL(Value1, Value2 ORDER BY ID) FROM MY_TABLE
    

    SELECT FIRST_NON_NULL(Value1, Value2 ORDER BY ID DESC) FROM MY_TABLE
    

    这将返回C,CC

    4 回复  |  直到 7 年前
        1
  •  9
  •   Giorgos Betsos    7 年前

    只要做:

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

    获得 最后的 非空值切换顺序:

    ORDER BY ID DESC
    

    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

        2
  •  5
  •   troy    5 年前

    对于那些需要在特定时间内这样做的人 大容量 ,这将成为一个问题和密集的,因为它可以转化为后端上的大量单个表点击。

    我有一个使用窗口函数的解决方案,可以解决大数据/分区的问题。

    GroupID | ID | Value1 | Value2
    --------------------------
    1       |  1 |  NULL  |   AA
    1       |  2 |   B    |  NULL
    1       |  3 |   C    |   CC
    1       |  4 |  NULL  |  NULL
    2       |  5 |   E    |   EE
    2       |  6 |   F    |  NULL
    2       |  7 |  NULL  |   GG
    2       |  8 |  NULL  |  NULL
    

    对于每个GroupID值

    GroupID | FirstValue1 | FirstValue2 | LastValue1 | LastValue2
    -------------------------------------------------------------
    1       | B           | AA          | C          | CC
    2       | E           | EE          | F          | GG
    

    如果我将前1个逻辑应用于缩放,并且我有很多行,那么它将返回以执行大量的单个表查询。然而,如果我使用窗口函数,我可以让它评估内存中的数据,以更有效地获取数据,尤其是在需要分区和大量数据时。

    以下是解决方案:

    SELECT
      GroupID,
      FirstValue1,
      FirstValue2,
      LastValue1,
      LastValue2
    FROM
      (
      SELECT
        GroupID,
        ID, Value1, Value2,
        -- Sets a rank so we can reduce to 1 row per GroupID in outer query
        DENSE_RANK() OVER (
          PARTITION BY GroupID
          ORDER BY ID
        ) IDRank,
        FIRST_VALUE(Value1) OVER (
          PARTITION BY GroupID
          ORDER BY
            CASE WHEN Value1 IS NULL THEN 2 ELSE 1 END, -- Prioritize non-null Value1
            ID                                          -- And ascending ID
        ) FirstValue1,
        FIRST_VALUE(Value2) OVER (
          PARTITION BY GroupID
          ORDER BY
            CASE WHEN Value2 IS NULL THEN 2 ELSE 1 END, -- Prioritize non-null Value2
            ID                                          -- And ascending ID
        ) FirstValue2,
        FIRST_VALUE(Value1) OVER (
          PARTITION BY GroupID
          ORDER BY
            CASE WHEN Value1 IS NULL THEN 2 ELSE 1 END, -- Prioritize non-null Value1
            ID DESC                                     -- And descending ID
        ) LastValue1,
        FIRST_VALUE(Value2) OVER (
          PARTITION BY GroupID
          ORDER BY
            CASE WHEN Value2 IS NULL THEN 2 ELSE 1 END, -- Prioritize non-null Value2
            ID DESC                                     -- And descending ID
        ) LastValue2
      FROM MY_TABLE
      ) BestValues
    WHERE IDRank = 1  --Ensures we get only one row per GroupID
    ORDER BY GroupID
    

    解释-第一个_值在每个不同的GroupID内求值(因为我们按GroupID设置分区)。在该窗口中,它计算该GroupID的行中具有非空值的情况,然后按ID排序(升序或降序)。 由于它是一个窗口函数,这将值放在原始粒度的记录级别上,因此我们还添加了一个稠密的_秩来进行秩,并使我们能够在外部查询中,将每个GroupID降到一行。


    p、 如果您想自己运行它,请在查询中包含以下内容,以将所需的样本数据生成到CTE中的“MY_表”中。

    WITH MY_TABLE AS (
      SELECT 0 as GroupID, 0 AS ID, CAST(NULL AS VARCHAR(10)) as Value1, CAST(NULL AS VARCHAR(10)) as Value2 WHERE 0=1 UNION ALL --Dummy row to set types
    
      SELECT 1 AS GroupID, 1 AS ID, NULL AS Value1, 'AA' AS Value2 UNION ALL
      SELECT 1 AS GroupID, 2 AS ID, 'B'  AS Value1, NULL AS Value2 UNION ALL
      SELECT 1 AS GroupID, 3 AS ID, 'C'  AS Value1, 'CC' AS Value2 UNION ALL
      SELECT 1 AS GroupID, 4 AS ID, NULL AS Value1, NULL AS Value2 UNION ALL
      SELECT 2 AS GroupID, 5 AS ID, 'E'  AS Value1, 'EE' AS Value2 UNION ALL
      SELECT 2 AS GroupID, 6 AS ID, 'F'  AS Value1, NULL AS Value2 UNION ALL
      SELECT 2 AS GroupID, 7 AS ID, NULL AS Value1, NULL AS Value2 UNION ALL
      SELECT 2 AS GroupID, 8 AS ID, NULL AS Value1, 'GG' AS Value2
    )
    
        3
  •  1
  •   SantiMunoz    4 年前

    Coalesce function

    你的问题最终会是

    SELECT COALESCE(Value ORDER BY ID) FROM MY_TABLE
    

    Example here

        4
  •  -4
  •   sanay shukla    7 年前

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