SQL 根据另一行中的值排除行

Posted

技术标签:

【中文标题】SQL 根据另一行中的值排除行【英文标题】:SQL exclude rows based on value in another row 【发布时间】:2019-03-04 14:42:16 【问题描述】:

我正在尝试排除另一行中存在值的行。

select * from TABLE1

ROW SEQ VALUE
1   1   HIGH
1   2   HIGH
1   3   LOW
1   4   HIGH
2   1   MED
2   2   HIGH
2   3   HIGH
2   4   LOW
2   5   HIGH
2   6   HIGH

所有数据都来自同一张表,我想要做的是排除 VALUE = 'LOW' 的行以及 SEQ

 ROW SEQ VALUE
1   4   HIGH
2   5   HIGH
2   6   HIGH

这是正在进行的工作,但它只排除了一行

select * from TABLE1
where not exists(select VALUE from TABLE1 
where ROW = ROW and VALUE = 'LOW' and SEQ <= SEQ)

我需要将其写入 where 原因,因为选择是硬编码的。我迷失了任何帮助将不胜感激。提前致谢!

【问题讨论】:

您的描述和示例数据似乎不匹配。 标记您正在使用的 DBMS。 【参考方案1】:
select *
from table1
left outer join (
    select row, max(seq) as seq
    from table1
    where value = 'low'
    group by row
) lows on lows.row = table1.row
where lows.row is null
   or table1.seq > lows.seq

【讨论】:

【参考方案2】:

您应该为表设置别名。我很惊讶你从这个查询中得到任何结果,因为你根本没有别名。

select * 
from TABLE1 As t0
where not exists(
    select VALUE 
    from TABLE1 As t1
    where t0.ROW = t1.ROW 
    and t1.VALUE = 'LOW' 
    and t0.SEQ <= t1.SEQ
)

【讨论】:

谢谢@Zohar 对不起,我是别名,但试图简化查询示例。但是,我没有在 not exists 子句中为表起别名。谢谢你成功了! Glad to help :-)【参考方案3】:

您可以使用具有累积方法的窗口函数:

select t.*
from (select t.*, sum(case when value = 'LOW' then 1 else 0 end) over (partition by row order by seq) as cnt
      from table t
     ) t
where cnt = 1 and value <> 'LOW';

【讨论】:

【参考方案4】:

对于您提到的结果,您似乎想要最后一个“低”之后的行。一种方法是:

select t1.*
from table1 t1
where t1.seq > (select max(t2.seq) from table1 tt1 where tt1.row = t1.row and tt1.value = 'LOW');

(注意:这需要一个“低”行。如果没有“低”行并且您希望返回所有行,则很容易将其添加到查询中。)

或者,类似地,使用not exists

select t1.*
from table1 t1
where not exists (select 1
                  from table1 tt1 
                  where tt1.row = t1.row and
                        tt1.seq > t.seq and
                        tt1.value = 'LOW'
                 );

这可能是您问题的最直接翻译。

但是,我更可能使用窗口函数:

select t1.*
from (select t1.*,
             max(case when t1.value = 'low' then seqnum end) over (partition by row) as max_low_seqnum
      from table1 t1
     ) t1
where seqnum > max_low_seqnum;

如果没有“低”行,您可能需要添加 or max_low_seqnum is null 以返回所有行。

【讨论】:

以上是关于SQL 根据另一行中的值排除行的主要内容,如果未能解决你的问题,请参考以下文章

SQL 根据其他行值排除行

SQL用一个字段排除另一个字段如何做

Db2 SQL 根据大量数据选择排除行的行

排除包含另一个列表中的值的列表项

选择包含所有提到的值并排除多对多关系中的重复项的名称

根据多个筛选条件 - SQL访问排除记录