【问题标题】:Is there a way to negate a WHERE clause in SQL?有没有办法否定 SQL 中的 WHERE 子句?
【发布时间】:2012-03-04 21:34:04
【问题描述】:

这是我的基本查询

select distinct a.projects , case when(billing_fy!=0)
then(select round(((sum(cost_project)/(sum(billing_fy)/((10/12)*365)))),2) 
     from table1 b      
     where a.projects = b.projects 
     group by projects)
else 0 end as "WIP days outstanding"
from table1 a

它会产生以下输出

Projects                        WIP days outstanding
History - AURANGABAD - NASIK    0
History - PUNE - MUMBAI         0
History - NASIK - MUMBAI        89.92
History - SASAGRAM - MUMBAI     0
History - SASAGRAM - MUMBAI     1386.52
History - AURANGABAD - MUMBAI   83.25

现在我需要显示除第 4 行之外的所有行。我首先使用case语句的原因是因为如果我这样做了( billing_fy!=0 子句是为了防止除以0引起的错误)

select projects,
round(((sum(cost_project)/(sum(billing_fy)/((10/12)*365)))),2) as "WIP days outstanding"
from table1
where billing_fy!=0
group by projects;

我会得到

Projects                        WIP days outstanding
History - SASAGRAM - MUMBAI     1386.52
History - NASIK - MUMBAI        89.92
History - AURANGABAD - MUMBAI   83.25

但我还需要展示其他两个地方

History - AURANGABAD - NASIK    0
History - PUNE - MUMBAI         0

此查询只显示我不想要的行。

select distinct a.projects , case when(billing_fy!=0)
then(select round(((sum(cost_project)/(sum(billing_fy)/((10/12)*365)))),2) from table1 b     where a.projects = b.projects group by projects)
else 0 end as "WIP days outstanding"
from table1 a
where (projects='History - SASAGRAM - MUMBAI' AND billing_fy=0);

并按预期给出输出

Projects                        WIP days outstanding
History - SASAGRAM - MUMBAI     0

现在是我的问题。 SQL中有没有办法否定WHERE子句?就像在 C++ 中一样,我只需要在子句前面使用 not 运算符来否定它。因为基本上,我想显示除上一行之外的所有行。

现在,我已经使用以下代码解决了显示除我不想要的行之外的所有行的问题

select distinct a.projects , case when(billing_fy!=0)
then(select round(((sum(cost_project)/(sum(billing_fy)/((10/12)*365)))),2) from table1 b   where a.projects = b.projects group by projects)
else 0 end as "WIP days outstanding"
from table1 a
where projects not in ('History - SASAGRAM - MUMBAI') and billing_fy!=0
union all
select distinct a.projects , case when(billing_fy!=0)
then(select round(((sum(cost_project)/(sum(billing_fy)/((10/12)*365)))),2) from table1 b   where a.projects = b.projects group by projects)
else 0 end as "WIP days outstanding"
from table1 a
where projects not in ('History - SASAGRAM - MUMBAI') and billing_fy=0
union all
select distinct a.projects , case when(billing_fy!=0)
then(select round(((sum(cost_project)/(sum(billing_fy)/((10/12)*365)))),2) from table1 b    where a.projects = b.projects group by projects)
else 0 end as "WIP days outstanding"
from table1 a
where projects='History - SASAGRAM - MUMBAI' and billing_fy!=0;

这会产生所需的输出

Projects                         WIP days outstanding
History - NASIK - MUMBAI         89.92
History - AURANGABAD - MUMBAI    83.25
History - AURANGABAD - NASIK     0
History - PUNE - MUMBAI          0
History - SASAGRAM - MUMBAI      1386.52

这只是一种破旧的做法,我想知道是否可以否定 WHERE 子句,或者一些“更简洁”的替代方法来做我想做的事情。

谢谢!!

附:我使用 SQL DeveloperOracle 11g(以防万一有人问)

编辑按要求输入值

Projects                      Cost_Project  Billing_FY
History - NASIK - MUMBAI      65696067.99   54937478.46
History - NASIK - MUMBAI      41385613.61   151909546.44
History - NASIK - MUMBAI      18029488.91   216353866.92
History - AURANGABAD - MUMBAI 33191393.23   57073935.95
History - AURANGABAD - MUMBAI 52681451.68   139055661.74
History - AURANGABAD - MUMBAI 74576522.31   390092578.24
History - PUNE - MUMBAI       0             0
History - PUNE - MUMBAI       0             0
History - PUNE - MUMBAI       0             0
History - SASAGRAM - MUMBAI   107540114.08  40653734.06
History - SASAGRAM - MUMBAI   209167760.1   28823862.66
History - SASAGRAM - MUMBAI   0             0
History - AURANGABAD - NASIK  0             0
History - AURANGABAD - NASIK  0             0
History - AURANGABAD - NASIK  0             0

【问题讨论】:

  • 请显示您的示例输入数据。我不太明白你的问题,但听起来你可能想使用外连接而不是 "where x = y"
  • 外连接不是用于两个单独的表吗?在任何情况下,查询都只是引用一个表(case 语句和 out 语句中的同一个表),我会将输入值编辑到问题的末尾
  • Oracle SQL 语法明确支持 NOT 运算符。 docs.oracle.com/cd/B19306_01/server.102/b14200/… 那么,为什么不试试呢?
  • “这只是一种简陋的做法”——旁观者认为简陋。愿意说出你为什么这么认为吗?
  • 谢谢。这就是我一直在寻找的。我的第一次尝试是使用 !在不起作用的语句之前。

标签: sql oracle oracle11g oracle-sqldeveloper


【解决方案1】:

请尝试以下方法:

select distinct a.projects , case when(billing_fy!=0)
then(select round(((sum(cost_project)/(sum(billing_fy)/((10/12)*365)))),2) from table b     where a.projects = b.projects group by projects)
else 0 end as "WIP days outstanding"
from table a
where (projects!='History - SASAGRAM - MUMBAI' AND billing_fy!=0);

【讨论】:

  • 我认为应该是“或”(参见德摩根定律en.wikipedia.org/wiki/De_Morgan%27s_laws
  • 这行不通。他实际上是在使用这个查询并使用其他查询执行UNION 以获得他需要的输出
【解决方案2】:

我认为应该这样做:

select distinct a.projects , case when(billing_fy!=0)
then(select round(((sum(cost_project)/(sum(billing_fy)/((10/12)*365)))),2) from table1 b     where a.projects = b.projects group by projects)
else 0 end as "WIP days outstanding"
from table1 a
where (projects != 'History - SASAGRAM - MUMBAI' OR billing_fy != 0);

【讨论】:

    【解决方案3】:

    我认为做你想做的最简单的方法是分组,而不是使用 distinct:

    select a.projects, 
           case when sum(billing_fy!=0)
                then (select round(((sum(cost_project)/(sum(billing_fy)/((10/12)*365)))),2) 
                      from table1 b
                      where a.projects = b.projects
                      group by projects)
                else 0 end as "WIP days outstanding"
    from table1 a
    group by a.projects
    

    【讨论】:

      【解决方案4】:

      如果我没看错你的问题,你想要的是not 运算符:

      select distinct a.projects , case when(billing_fy!=0)
      then(select round(((sum(cost_project)/(sum(billing_fy)/((10/12)*365)))),2) 
      from table1 b     
      where a.projects = b.projects group by projects)
      else 0 end as "WIP days outstanding"
      from table1 a
      where not (projects='History - SASAGRAM - MUMBAI' AND billing_fy=0);
      

      正如@ShannonSeverance 指出的那样,如果您在任一字段中都有空值,这将导致问题,因为not (false and null) 的计算结果为空,这将被视为假。如果您需要使这个 null 安全,以便它只排除具有这两个值的行,您需要执行以下操作:

      select distinct a.projects , case when(billing_fy!=0)
      then(select round(((sum(cost_project)/(sum(billing_fy)/((10/12)*365)))),2) 
      from table1 b
      where a.projects = b.projects group by projects)
      else 0 end as "WIP days outstanding"
      from table1 a
      where (not (projects='History - SASAGRAM - MUMBAI' AND billing_fy=0))
            or projects is null 
            or billing_fy is null;
      

      【讨论】:

      • 需要注意的一个问题是 SQL 支持三值逻辑。与 NULL 的比较返回 UNKNOWN。不未知就是未知。因此,您可以有一个 where 子句排除某些行,因为它们评估为未知,并且说 where not (prior where criteria) 仍将排除这些相同的行。
      猜你喜欢
      • 2023-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多