我有一张带复合键的表。每行都有一个值。不应返回具有负值的行。如果存在两行,其中Key1和Key2相同且一行中的值与另一行* -1中的值相同,则不应返回任何行。但是,如果存在具有相同Key1的第三行和具有正值的Key2,则应返回该行。这是一个示例表:
Key1 Key2 Key3 Value
----------------------------
1 1 1 500.00
1 1 2 -500.00
1 1 3 500.00
1 2 1 250.00
1 3 1 100.00
1 3 2 -100.00
查询结果应为:
Key1 Key2 Key3 Value
----------------------------
1 1 3 500.00
1 2 1 250.00
那么什么是可以给我这个结果的查询?谢谢!
其他信息:
@Jacky,不应返回100.00,因为Key1和Key2相同时存在另一行,但该值与-100.00完全相反。
@ Eralper,1,1,1和1,1,2相互抵消,但应返回1,1,3。
@ Zohar,我正在使用SQL Server 2014 SP1。 Key1和Key2相同的行是唯一计为匹配的行。
另外,抱歉我最初没有包含此内容,当应该返回一行时,它应该是Key3列中值最大的行。例如,1,1,2取消1,1,1,并且应返回1,1,3。
这些是我们的采购部门已输入并且我们的用户可以支付的行的表格。对于1,1,1,采购部表示此行可以现在支付。后来,在1,1,2,采购说这不能支付。之后,在1,1,3采购上说,可以毕竟可以支付。
这就是为什么在这个时间点,我只能返回结果表中显示的2行。
答案 0 :(得分:1)
这就是我最终的结果:
SELECT
Key1
,Key2
,Key3
,Value
FROM (
SELECT
Key1,
Key2,
Key3,
Value,
SUM(Value) OVER (PARTITION BY Key1, Key2, ABS(Value)) as valueSum,
ROW_NUMBER() OVER (PARTITION BY Key1, Key2, ABS(Value) ORDER BY Key3 DESC) as rowNumber
FROM [Etads].[dbo].[TestTlsc]
) a
WHERE valueSum > 0
AND rowNumber = 1
如果值"取消",则所有值的总和将为零。因此" WHERE valueSum> 0"
ORDERing BY Key3 DESC将max Key3置于rowNumber = 1。
谢谢!
答案 1 :(得分:0)
请在测试环境中测试SQL CTE query
正如我上面评论的那样,我认为1,1,1是输出列表的候选者,因为下面的查询建议
我还使用Row_Number()SQL函数到Count() with Over clause
我知道这是一个复杂的查询,我讨厌它:) 但是你的要求一目了然有点难以回答
我希望它有所帮助,
with cteKeys as (
select ROW_NUMBER() over (Order By key1,key2,key3) Id, * from keys
), cteList as (
select
k1.Id as key1Id,
k2.Id as key2Id,
k1.key1 as key11,
k1.key2 as key12,
k1.key3 as key13,
k2.key1 as key21,
k2.key2 as key22,
k2.key3 as key23,
k1.value as key1val,
k2.value as key2val,
case when (
k1.key1 = k2.key1 and
k1.key2 = k2.key2 and
k1.key3 <> k2.key3
) then 110
when (
k1.key1 = k2.key1 and
k1.key2 <> k2.key2 and
k1.key3 = k2.key3
) then 101
when (
k1.key1 <> k2.key1 and
k1.key2 = k2.key2 and
k1.key3 = k2.key3
) then 011
end as match
from cteKeys k1
left join cteKeys k2 on
(
k1.key1 = k2.key1 and
k1.key2 = k2.key2 and
k1.key3 <> k2.key3
) or
(
k1.key1 = k2.key1 and
k1.key2 <> k2.key2 and
k1.key3 = k2.key3
) or
(
k1.key1 <> k2.key1 and
k1.key2 = k2.key2 and
k1.key3 = k2.key3
)
)
--select * from cteList
, cteMatches as (
select
*,
count(key2Id) over (partition by key1Id, match) cnt,
isDeleted0 = case when (count(key2Id) over (partition by key1Id, match)) = 0 then 0 else null end
from cteList
), resultCTE as (
select *,
case when (cnt = 2 and key1val <> -1 * key2val and key1val > 0 and key2val > 0) then 0 end as isDeleted2,
case when (cnt = 1 and key1val = -1 * key2val) then 1 end as isDeleted1
from cteMatches
)
--select * from resultCTE
, final as (
select * --distinct key1Id, key11,key12,key13
from resultCTE
where isDeleted0 = 0
union all
select * --distinct key1Id, key11,key12,key13
from resultCTE
where isDeleted2 = 0
and not exists (
select * from resultCTE t where t.key1Id = resultCTE.key1Id and isDeleted1 = 1
)
union all
select * from resultCTE where coalesce(coalesce(isDeleted0,isDeleted2),isDeleted1) is null
)
--select * from cteMatches
select distinct * from cteKeys where Id in (
select key1Id
from final
) and Value > 0
这是输出