【问题标题】:Remove rows to the nth position if it found continuous NULL如果发现连续的 NULL,则将行删除到第 n 个位置
【发布时间】:2021-06-03 16:10:01
【问题描述】:

我正面临需要帮助的情况。我使用的是 SQL Server 2014。

我的查询是我必须删除 NULL 值的行,但前提是它从一开始就连续找到,如下所示,我给出了一些输入和输出示例。

Sample Input 1 : 

Sample Output 1 :

Sample Input 2 :

Sample Output 2: (because from the starting it doesn't have null values. Null values are in the middle)

Sample Input 3:

Sample Output 3: (it will return blank table as all the null values get removed)

提前致谢。

【问题讨论】:

  • 如果有 2 个起始空值,然后是一个值,然后是另一个空值怎么办?您只想删除第一个空值吗?
  • 你所说的“从一开始”是什么意思?特定日期的第一个条目,特定用户的第一个实例??
  • @JaviTorre 只有 StartTime 可以有 NULL 值。因此,如果有 2 条记录并且在 StartTime 中都具有 NULL,那么都应该删除它们,但是如果第一行没有 NULL,而第二行有 NULL,那么它会按原样显示。 (参见示例输入和输出 2)。
  • 如果 1,2,4 不为空,6 为空怎么办?
  • @PankajSanwal “从开始”是指第 1 行到第 n 行,它将在 StartTime 中获得 NULL,但只能连续。如果在第 3 行 StartTime 中不为空,那么它将删除开始的 2 行,因为两行都为空。

标签: sql sql-server database tsql


【解决方案1】:

这不是 SQL Server,但可能会提示您如何继续。计算排序的空值(如果为空,则求和 0),然后去掉那些为 0 的值。

with aux (id, v) as (
    select 1, null from dual union all
    select 2, null from dual union all
    select 3, 2 from dual union all
    select 4, null from dual union all
    select 5, 2 from dual),
aux1 as (
    SELECT
        a.*,
        SUM(
            CASE
                WHEN v IS NULL THEN
                    0
                ELSE
                    1
            END
        ) OVER(
        ORDER BY
            id
        ) h1
    FROM
        aux a
)
SELECT
    *
FROM
    aux1
where h1>0;

输出:

ID  V   H
---------
3   2   1
4       1
5   2   2

【讨论】:

  • from dual 不是 SQL Server 语法
【解决方案2】:

您可以尝试以下方法。您可以在 SSMS 中运行每个场景。

场景一

DECLARE @data table ( InstanceID int, [TimeStamp] datetime, StartTime datetime );
INSERT INTO @data VALUES
    ( 1, '08/22/2020 07:06:00', NULL ), 
    ( 2, '08/22/2020 12:30:00', NULL ), 
    ( 4, '08/22/2020 14:32:00', NULL ), 
    ( 6, '08/22/2020 17:13:00', '08/22/2020 17:30:00' );

WITH cte AS (
    SELECT
        ROW_NUMBER() OVER ( ORDER BY [TimeStamp] ) AS id,
        InstanceID,
        [TimeStamp],
        StartTime
    FROM @data
)
SELECT
    InstanceID, [TimeStamp], StartTime
FROM cte
OUTER APPLY (

    SELECT CASE 
        WHEN cte.id = 1 AND cte.StartTime IS NULL THEN 1
        WHEN cte.id = 1 AND cte.StartTime IS NOT NULL THEN 0
        WHEN cte.StartTime IS NULL AND ( SELECT COUNT ( * ) FROM cte AS c WHERE c.id < cte.id AND c.StartTime IS NOT NULL ) > 0 THEN 0
        WHEN cte.StartTime IS NOT NULL THEN 0
        ELSE 1
    END AS Exclude

) AS x
WHERE
    Exclude = 0
ORDER BY
    [TimeStamp];

返回

+------------+-------------------------+-------------------------+
| InstanceID |        TimeStamp        |        StartTime        |
+------------+-------------------------+-------------------------+
|          6 | 2020-08-22 17:13:00.000 | 2020-08-22 17:30:00.000 |
+------------+-------------------------+-------------------------+

场景二

DECLARE @data table ( InstanceID int, [TimeStamp] datetime, StartTime datetime );
INSERT INTO @data VALUES
    ( 1, '08/22/2020 07:06:00', '08/22/2020 07:06:00' ), 
    ( 2, '08/22/2020 12:30:00', NULL ), 
    ( 4, '08/22/2020 14:32:00', NULL ), 
    ( 6, '08/22/2020 17:13:00', '08/22/2020 17:30:00' );

WITH cte AS (
    SELECT
        ROW_NUMBER() OVER ( ORDER BY [TimeStamp] ) AS id,
        InstanceID,
        [TimeStamp],
        StartTime
    FROM @data
)
SELECT
    InstanceID, [TimeStamp], StartTime
FROM cte
OUTER APPLY (

    SELECT CASE 
        WHEN cte.id = 1 AND cte.StartTime IS NULL THEN 1
        WHEN cte.id = 1 AND cte.StartTime IS NOT NULL THEN 0
        WHEN cte.StartTime IS NULL AND ( SELECT COUNT ( * ) FROM cte AS c WHERE c.id < cte.id AND c.StartTime IS NOT NULL ) > 0 THEN 0
        WHEN cte.StartTime IS NOT NULL THEN 0
        ELSE 1
    END AS Exclude

) AS x
WHERE
    Exclude = 0
ORDER BY
    [TimeStamp];

返回

+------------+-------------------------+-------------------------+
| InstanceID |        TimeStamp        |        StartTime        |
+------------+-------------------------+-------------------------+
|          1 | 2020-08-22 07:06:00.000 | 2020-08-22 07:06:00.000 |
|          2 | 2020-08-22 12:30:00.000 | NULL                    |
|          4 | 2020-08-22 14:32:00.000 | NULL                    |
|          6 | 2020-08-22 17:13:00.000 | 2020-08-22 17:30:00.000 |
+------------+-------------------------+-------------------------+

场景三

DECLARE @data table ( InstanceID int, [TimeStamp] datetime, StartTime datetime );
INSERT INTO @data VALUES
    ( 1, '08/22/2020 07:06:00', NULL ), 
    ( 2, '08/22/2020 12:30:00', NULL ), 
    ( 4, '08/22/2020 14:32:00', NULL );

WITH cte AS (
    SELECT
        ROW_NUMBER() OVER ( ORDER BY [TimeStamp] ) AS id,
        InstanceID,
        [TimeStamp],
        StartTime
    FROM @data
)
SELECT
    InstanceID, [TimeStamp], StartTime
FROM cte
OUTER APPLY (

    SELECT CASE 
        WHEN cte.id = 1 AND cte.StartTime IS NULL THEN 1
        WHEN cte.id = 1 AND cte.StartTime IS NOT NULL THEN 0
        WHEN cte.StartTime IS NULL AND ( SELECT COUNT ( * ) FROM cte AS c WHERE c.id < cte.id AND c.StartTime IS NOT NULL ) > 0 THEN 0
        WHEN cte.StartTime IS NOT NULL THEN 0
        ELSE 1
    END AS Exclude

) AS x
WHERE
    Exclude = 0
ORDER BY
    [TimeStamp];

返回

+------------+-----------+-----------+
| InstanceID | TimeStamp | StartTime |
+------------+-----------+-----------+

【讨论】:

    【解决方案3】:
    /* scenario 1 */
    declare @t table ( InstanceID int, [TimeStamp] datetime, StartTime datetime );
    insert into @t values
        ( 1, '08/22/2020 07:06:00', null ), 
        ( 2, '08/22/2020 12:30:00', null ), 
        ( 4, '08/22/2020 14:32:00', null ), 
        ( 6, '08/22/2020 17:13:00', '08/22/2020 17:30:00' );
    
    with t_cte as (
        select *,
               row_number() over (order by InstanceID) rn,
               sum(case when StartTime is null then 1 else 0 end) over (order by InstanceID) is_null
        from @t)
    select *
    from @t t
    where not exists(select * 
                     from t_cte tc
                     where tc.InstanceID=t.InstanceID
                           and rn=is_null);
    
    InstanceID  TimeStamp                   StartTime
    6           2020-08-22 17:13:00.000     2020-08-22 17:30:00.000
    
    /* scenario 2 */
    declare @t table ( InstanceID int, [TimeStamp] datetime, StartTime datetime );
    insert into @t values
        ( 1, '08/22/2020 07:06:00', '08/22/2020 07:06:00' ), 
        ( 2, '08/22/2020 12:30:00', null ), 
        ( 4, '08/22/2020 14:32:00', null ), 
        ( 6, '08/22/2020 17:13:00', '08/22/2020 17:30:00' );
    
    with t_cte as (
        select *,
               row_number() over (order by InstanceID) rn,
               sum(case when StartTime is null then 1 else 0 end) over (order by InstanceID) is_null
        from @t)
    select *
    from @t t
    where not exists(select * 
                     from t_cte tc
                     where tc.InstanceID=t.InstanceID
                           and rn=is_null);
    
    InstanceID  TimeStamp                   StartTime
    1           2020-08-22 07:06:00.000     2020-08-22 07:06:00.000
    2           2020-08-22 12:30:00.000     NULL
    4           2020-08-22 14:32:00.000     NULL
    6           2020-08-22 17:13:00.000     2020-08-22 17:30:00.000
    
    /* scenario 3 */
    declare @t table ( InstanceID int, [TimeStamp] datetime, StartTime datetime );
    insert into @t values
        ( 1, '08/22/2020 07:06:00', null ), 
        ( 2, '08/22/2020 12:30:00', null ), 
        ( 4, '08/22/2020 14:32:00', null ), 
        ( 6, '08/22/2020 17:13:00', null );
    
    with t_cte as (
        select *,
               row_number() over (order by InstanceID) rn,
               sum(case when StartTime is null then 1 else 0 end) over (order by InstanceID) is_null
        from @t)
    select *
    from @t t
    where not exists(select * 
                     from t_cte tc
                     where tc.InstanceID=t.InstanceID
                           and rn=is_null);
    
    no rows returned
    

    【讨论】:

      【解决方案4】:

      注意:取消注释您要测试的示例。

      试试这个:

      DECLARE @SampleTable    TABLE 
              (InstanceID int, TStamp datetime, StartTime datetime)
      ;
      INSERT INTO @SampleTable
      VALUES  
      /**/
              (1, '8/22/2020 07:06', NULL)
          ,   (2, '8/22/2020 12:30', NULL)
          ,   (4, '8/22/2020 14:32', NULL)
          ,   (6, '8/22/2020 17:13', '8/22/2020 17:13')
      
      /*
              (1, '8/22/2020 07:06', '8/22/2020 07:06')
          ,   (2, '8/22/2020 12:30', NULL)
          ,   (4, '8/22/2020 14:32', NULL)
          ,   (6, '8/22/2020 17:13', '8/22/2020 17:13')
      */
      /*
              (1, '8/22/2020 07:06', NULL)
          ,   (2, '8/22/2020 12:30', NULL)
          ,   (4, '8/22/2020 14:32', NULL)
      */
      ;
      DECLARE @FirstInstanceIsNull bit 
          =   CASE WHEN (
                          SELECT  TOP 1 StartTime 
                          FROM    @SampleTable 
                          ORDER BY InstanceID
                       ) IS NULL 
                  THEN 1 
                  ELSE 0 
              END
      ;
      SELECT  *
      FROM    @SampleTable
      WHERE   (@FirstInstanceIsNull = 0 )
          OR  (@FirstInstanceIsNull = 1 AND StartTime IS NOT NULL)
      

      【讨论】:

        猜你喜欢
        • 2021-06-08
        • 2020-11-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-10-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多