Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL。如果没有相应的正值,则隐藏负值_Sql_Oracle - Fatal编程技术网

SQL。如果没有相应的正值,则隐藏负值

SQL。如果没有相应的正值,则隐藏负值,sql,oracle,Sql,Oracle,我有一个SQL语句,如果正数等于负数,它将隐藏记录。但是,如果我意外输入了不正确的负数,则该负数也会在报告中显示为正数,因为我正在使用ABS函数。我不想那样 比如说,, 我的Oracle测试表中有以下布局: +------+---------+----------+-----------+ | user | project | contract | amount | +------+---------+----------+-----------+ | abc | p123 | c

我有一个SQL语句,如果正数等于负数,它将隐藏记录。但是,如果我意外输入了不正确的负数,则该负数也会在报告中显示为正数,因为我正在使用ABS函数。我不想那样

比如说,, 我的Oracle测试表中有以下布局:

+------+---------+----------+-----------+
| user | project | contract | amount    |
+------+---------+----------+-----------+
| abc  | p123    | c123     |  100.00   |
+------+---------+----------+-----------+
| abc  | p123    | c123     |  200.00   |
+------+---------+----------+-----------+
| abc  | p123    | c123     |  150.00   |
+------+---------+----------+-----------+
| abc  | p123    | c123     | -150.00   |
+------+---------+----------+-----------+

上面的SQL语句将返回前两条记录,这正是我想要的

我遇到的问题是,如果负-150.00错误地输入为-140.00,上面的SQL语句将返回所有四条记录,负-140.00将变为正140.00,这不是我想要的。它应该只显示前三条记录,并隐藏负数-140.00,或任何不具有相等正数的负数

我如何隐藏负数-140.00,只显示前三个记录,并且仍然能够使用GROUP BY和HAVING


提前感谢。

您可以按如下方式使用exists:

SELECT user, project, contract, ABS(amount)
FROM test_table t
WHERE contract = 'c123'
AND (amount >= 0 
     or exists (select 1 from test_table tin
                 where t.rowid <> tin.rowid
                   and t.contract = tin.contract 
                   and t.amount + tin.amount = 0)
    )

您可以按如下方式使用exists:

SELECT user, project, contract, ABS(amount)
FROM test_table t
WHERE contract = 'c123'
AND (amount >= 0 
     or exists (select 1 from test_table tin
                 where t.rowid <> tin.rowid
                   and t.contract = tin.contract 
                   and t.amount + tin.amount = 0)
    )

您可以使用下面的选项获得结果

        WITH data
         AS (SELECT *
             FROM   your table
             WHERE contract = 'c123'
              ),
         d2
         AS (SELECT Row_number()
                      over (
                        PARTITION BY user, project, contract,amount
                        ORDER BY user, project, contract) rw,
                    d.*
             FROM   data d)
    SELECT *
    FROM   (SELECT d.user1,
                   project1,
                   contract,
                   SUM(amount)
                     over(
                       PARTITION BY user, project, contract,Abs(amount), rw
                       ORDER BY user, project, contract) AS amount
            FROM   d2 d)
    WHERE  amount > 0; 

您可以使用下面的选项获得结果

        WITH data
         AS (SELECT *
             FROM   your table
             WHERE contract = 'c123'
              ),
         d2
         AS (SELECT Row_number()
                      over (
                        PARTITION BY user, project, contract,amount
                        ORDER BY user, project, contract) rw,
                    d.*
             FROM   data d)
    SELECT *
    FROM   (SELECT d.user1,
                   project1,
                   contract,
                   SUM(amount)
                     over(
                       PARTITION BY user, project, contract,Abs(amount), rw
                       ORDER BY user, project, contract) AS amount
            FROM   d2 d)
    WHERE  amount > 0; 
您可以在不存在的情况下执行此操作:

或者,如果仅合同不足以定义所需的行:

select t.* from test_table t
where t.contract = 'c123' and t.amount > 0
and not exists (
  select 1 from test_table
  where "user" = t."user" and project = t.project 
    and contract = t.contract and amount = -t.amount
)
请参阅。

您可以在不存在的情况下执行此操作:

或者,如果仅合同不足以定义所需的行:

select t.* from test_table t
where t.contract = 'c123' and t.amount > 0
and not exists (
  select 1 from test_table
  where "user" = t."user" and project = t.project 
    and contract = t.contract and amount = -t.amount
)

请参阅。

任何天真地使用不存在或类似结构的方法都是危险的。原因很简单:你可以有重复的

因此,我建议使用row_number枚举金额,然后使用:

with tt as (
      select tt.*,
             row_number() over (partition by user, project, contract, amount order by user) as seqnum
      from test_table tt
     ) tt
select tt.*
from tt
where not exists (select 1
                  from tt tt2
                  where tt2.user = tt.user and
                        tt2.project = tt.project and
                        tt2.contract = tt.contract and
                        tt2.seqnum = tt.seqnum and
                        tt2.amount = - tt.amount
                 );

任何天真地使用不存在或类似结构的方法都是危险的。原因很简单:你可以有重复的

因此,我建议使用row_number枚举金额,然后使用:

with tt as (
      select tt.*,
             row_number() over (partition by user, project, contract, amount order by user) as seqnum
      from test_table tt
     ) tt
select tt.*
from tt
where not exists (select 1
                  from tt tt2
                  where tt2.user = tt.user and
                        tt2.project = tt.project and
                        tt2.contract = tt.contract and
                        tt2.seqnum = tt.seqnum and
                        tt2.amount = - tt.amount
                 );

如果有一个额外的150,而不是,150和-150,它将不会按照您的回答显示。不,它不会显示,因为没有什么可以区分它们。如果有其他列,如可以使用的日期,则OP将澄清。如果有一个额外的150,而不是,150和-150根据您的回答,它不会显示。不会显示,因为没有任何东西可以区分它们。如果有其他列(如日期)可以使用,则OP将澄清。如果有多个金额具有相同的值怎么办?好问题。这是可能的。如果有多个金额具有相同的价值呢?好问题。这是一种可能性。如果我需要显示负数,但没有相应的正数,这很有效。我会保留这个以备将来的需求变更。谢谢!如果我还需要显示负数,但没有相应的正数,那么这个方法很有效。我会保留这个以备将来的需求变更。谢谢!