我有一个与此问题密切相关的SQL问题 - SQL - Need to find duplicate records but EXCLUDE reversed transactions
我需要使用(如果可能的话)非过程SQL删除记录集的所有反转“对”。特定的rdbms是Oracle 11g,但我希望SQL尽可能通用,因此可以在SQL Server 2008中使用相同的策略。示例记录集如下所示:
ROW | DATE | QTY | FUEL_TYPE | REVERSAL |
1 | 01-MAY-12 | 23.3 | DSL | N |
2 | 01-MAY-12 | -23.3 | DSL | Y |
3 | 01-MAY-12 | 23.3 | DSL | N |
4 | 01-MAY-12 | 23.3 | DSL | N |
5 | 01-MAY-12 | 23.3 | DSL | N |
6 | 01-MAY-12 | 18.6 | DSL | N |
7 | 01-MAY-12 | -18.6 | DSL | Y |
8 | 01-MAY-12 | 14.9 | GAS | N |
查询的预期结果会将此记录集减少为:
ROW | DATE | QTY | FUEL_TYPE | REVERSAL |
3 | 01-MAY-12 | 23.3 | DSL | N |
4 | 01-MAY-12 | 23.3 | DSL | N |
5 | 01-MAY-12 | 23.3 | DSL | N |
8 | 01-MAY-12 | 14.9 | GAS | N |
请注意,重复是可能的,但总是需要删除反转“对”。
修改的 行和行号无关紧要,仅用于说明。删除哪些记录并不重要,只是总是存在“对” - 正数和负数。因此,例如,第2行可以与1,3,4或5配对并删除。
此外,填充表和表结构本身的逻辑由供应商软件控制,并且不包括在反转记录中被反转的记录的原始ID。我真的无法控制这个。 /编辑
顺便说一下,如果更改MINUS关键字以使其功能类似于UNION和UNION ALL,我会喜欢它,因为MINUS只删除与第二个记录集匹配的单个行集,但MINUS ALL删除每个< / em>与第二个记录集中的值匹配的行。如果是这样的话,这个问题就会变得微不足道(至少对于我大脑的想法)。
答案 0 :(得分:0)
您遇到的问题是撤消并未直接分配给他们正在撤销的交易。
假设逆转是完全逆转,您可以采取以下方法。对于给定的一组交易信息,枚举逆转和非逆转。然后,采取所有不匹配的非逆转。
以下是执行此操作的SQL示例:
with t as
(
select row, date, qty, fuel_type, reversal,
ROW_NUMBER() over (partition by row, date, qty, fuel_type, reversal) as rownum
from table
)
select *
from
(
select *
from t
where t.reversal = 'N'
) n
left outer join
(
select *
from t
where t.reversal = 'Y'
) y
on n.date = y.date
and n.qty = y.qty
and n.fuel_type = y.fuel_type
and n.rownum = y.rownum
where n.row is null
这应该在SQL和Oracle中都有效,因为它们都支持row_number窗口/分析函数。
请注意,此解决方案不保证撤消是正确的。它还假设在原始交易的同一天发生了逆转。
答案 1 :(得分:0)
事实证明我正以一种非常可怕的方式看待这个问题。我没有找到精确反转对,而只是用GROUP BY做了一个SUM,所以只有我关心的值保持不变。
最终结果是交易最终会有所不同 - 尤其是在我的情况下,真正的交易表实际上是日期时间值而不是日期。
SELECT SUM(QTY) AS newQTY, DATE, FUEL_TYPE
FROM fuel_transactions
GROUP BY DATE, FUEL_TYPE
如果您需要维护事务的id,或者如果您遇到多个事务发生在 exact 的情况下,那么唯一一次这不会产生您真正想要的值em>同一时间。