SQL。如果没有相应的正值,则隐藏负值
我有一个SQL语句,如果正数等于负数,它将隐藏记录。但是,如果我意外输入了不正确的负数,则该负数也会在报告中显示为正数,因为我正在使用ABS函数。我不想那样 比如说,, 我的Oracle测试表中有以下布局:SQL。如果没有相应的正值,则隐藏负值,sql,oracle,Sql,Oracle,我有一个SQL语句,如果正数等于负数,它将隐藏记录。但是,如果我意外输入了不正确的负数,则该负数也会在报告中显示为正数,因为我正在使用ABS函数。我不想那样 比如说,, 我的Oracle测试表中有以下布局: +------+---------+----------+-----------+ | user | project | contract | amount | +------+---------+----------+-----------+ | abc | p123 | c
+------+---------+----------+-----------+
| 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将澄清。如果有多个金额具有相同的值怎么办?好问题。这是可能的。如果有多个金额具有相同的价值呢?好问题。这是一种可能性。如果我需要显示负数,但没有相应的正数,这很有效。我会保留这个以备将来的需求变更。谢谢!如果我还需要显示负数,但没有相应的正数,那么这个方法很有效。我会保留这个以备将来的需求变更。谢谢!