Sql 删除一列中具有特定值且同一行或连续行的另一列中缺少值的行

Sql 删除一列中具有特定值且同一行或连续行的另一列中缺少值的行,sql,postgresql,gaps-and-islands,Sql,Postgresql,Gaps And Islands,我的数据集由不同公司的每日时间序列组成,我使用PostgreSQL。 我的数据集中有一个指示符变量,取值为1,-1,大部分时间为0。如果指标变量不为0,且某公司在该日(指标日)或第二天的另一列中缺少值,则该公司应完全从数据集中排除 我们可以考虑以下示例数据: date company indicator value 2012-01-02 A 0 2 2012-01-02 B 0

我的数据集由不同公司的每日时间序列组成,我使用PostgreSQL。 我的数据集中有一个指示符变量,取值为1,-1,大部分时间为0。如果指标变量不为0,且某公司在该日(指标日)或第二天的另一列中缺少值,则该公司应完全从数据集中排除

我们可以考虑以下示例数据:

date             company   indicator   value
2012-01-02       A         0           2
2012-01-02       B         0           9
2012-01-02       C         0           1
2012-01-02       D         0           3
2012-01-03       A         1           NULL
2012-01-03       B         0           NULL
2012-01-03       C        -1           1
2012-01-03       D         0           2
2012-01-04       A         0           1
2012-01-04       B         0           1
2012-01-04       C         0           NULL
2012-01-04       D         1           4
2012-01-05       A         0           4
2012-01-05       B         0           2
2012-01-05       C         0           1
2012-01-05       D         0           7
因此,A必须被排除在外,因为它在指标日缺少一个值,而C是因为它在指标日的第二天缺少一个值

我尝试了以下方法:

    CREATE TABLE to_delete
    AS SELECT * FROM mytable
    WHERE company IN(
                   SELECT company 
                   FROM mytable 
                   WHERE date BETWEEN (SELECT date FROM mytable WHERE indicator != 0)
                          AND (SELECT date+1 FROM mytable WHERE indicator != 0) 
                   AND indicator != 0)
    AND date BETWEEN (SELECT date FROM mytable WHERE indicator != 0)
                 AND (SELECT date+1 FROM mytable WHERE indicator != 0) 

    DELETE FROM mytable WHERE company in (SELECT DISTINCT company FROM to_delete);
如果示例数据集中只存在一个不等于零的指示符值,则该方法有效。对于多行,PostgreSQL返回一个错误,表示我的子查询返回了多行


我真的在努力解决这个问题。您是否知道一种解决方案,或者可能是实现所需结果的完全其他方法

我会用一个

仅删除有问题的行

Ervin的变体看起来更清晰,如果这是少量的数据,并且子选择的数量无关紧要。
SELECT * FROM tbl t
-- DELETE FROM tbl t
WHERE  indicator <> 0
AND EXISTS (
   SELECT 1
   FROM   tbl t1
   WHERE  day IN (t.day, t.day + 1)
   AND    t1.company = t.company
   AND    t1.value IS NULL
   )
DELETE FROM tbl t
USING (
    SELECT DISTINCT company
    FROM   tbl t
    WHERE  indicator <> 0
    AND EXISTS (
        SELECT 1
        FROM   tbl t1
        WHERE  day IN (t.day, t.day + 1)
        AND    t1.company = t.company
        AND    t1.value IS NULL
        )
    ) del
WHERE t.company = del.company
DELETE FROM test WHERE company IN (
WITH 
    for_check AS (SELECT date, company FROM test WHERE indicator != 0)
SELECT test.company 
FROM test 
INNER JOIN for_check fc 
    ON test.date IN (fc.date, fc.date + 1) 
        AND fc.company = test.company 
WHERE test.value IS NULL
)