删除表中的行,这些行是每个组的其他行的总和

时间:2016-05-20 06:58:44

标签: sql sql-server

T分组行,并在每个组中查找最大或最小的行(如果值为负),该行中其他行的总和,并删除该行(每个组一个),如果group没有足够的元素来查找sum或者足够但没有行指示其他的总和没有发生

CREATE TABLE Test (
    T   varchar(10),
    V   int
);
INSERT INTO Test
    VALUES ('A',  4), 
           ('B', -5), 
           ('C',  5), 
           ('A',  2), 
           ('B', -1), 
           ('C', 10), 
           ('A',  2), 
           ('B', -4), 
           ('C',  5), 
           ('D',  0);

预期结果:

A    2
A    2
B   -1
B   -4
C    5
C    5
D    0

7 个答案:

答案 0 :(得分:1)

与评论一样,要求似乎很奇怪。下面的代码假定求和已经预先填充,只要最高值不是0就删除最大值/最小值。

if object_id('tempdb..#test') is not null
drop table #test

CREATE TABLE #Test (
    T   varchar(10),
    V   int
);
INSERT INTO #Test
    VALUES ('A', 4), ('B', -5), ('C', 5), ('A', 2), ('B', -1), ('C', 10), ('A', 2), ('B', -4), ('C', 5), ('D', 0);


if object_id('tempdb..#test2') is not null
drop table #test2

SELECT
T,
V,
ABS(V) as absV
INTO #TEST2
FROM #TEST
SELECT * FROM #TEST2

if object_id('tempdb..#max') is not null
drop table #max

SELECT
T,
MAX(absV) AS MaxAbsV
INTO #Max
FROM #TEST2
GROUP BY T
HAVING MAX(AbsV) != 0



DELETE #TEST2
FROM #TEST2
INNER JOIN #MAX ON #TEST2.T = #MAX.T AND #TEST2.absV = #Max.MaxAbsV

SELECT * FROM #TEST2
ORDER BY T ASC

答案 1 :(得分:1)

; with cte as
(
    select  T, V, 
        R = row_number() over (partition by T order by ABS(V) desc),
        C = count(*) over (partition by T)
    from    Test 
)
delete  c
from    cte c
    inner join
    (
        select  T, S = sum(V)
        from    cte
        where   R   <> 1
        group by T
    ) s on  c.T = s.T
where   c.C >= 3 
and c.R = 1
and c.V = s.S

答案 2 :(得分:1)

使用ABS而不存在

Error       The "LinkAssemblies" task failed unexpectedly.
Xamarin.Android.XamarinAndroidException: error XA2006: Reference to metadata item 'System.Runtime.InteropServices.StandardOleMarshalObject' (defined in 'System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089') from 'System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' could not be resolved. ---> Mono.Cecil.ResolutionException: Failed to resolve System.Runtime.InteropServices.StandardOleMarshalObject
   at Mono.Linker.Steps.MarkStep.MarkType(TypeReference reference)
   at MonoDroid.Tuner.MonoDroidMarkStep.MarkType(TypeReference reference)
   at Mono.Linker.Steps.MarkStep.MarkType(TypeReference reference)
   at MonoDroid.Tuner.MonoDroidMarkStep.MarkType(TypeReference reference)
   at Mono.Linker.Steps.MarkStep.InitializeType(TypeDefinition type)
   at Mono.Linker.Steps.MarkStep.InitializeAssembly(AssemblyDefinition assembly)
   at Mono.Linker.Steps.MarkStep.Initialize()
   at Mono.Linker.Steps.MarkStep.Process(LinkContext context)
   at Mono.Linker.Pipeline.Process(LinkContext context)
   at MonoDroid.Tuner.Linker.Process(LinkerOptions options, LinkContext& context)
   at Xamarin.Android.Tasks.LinkAssemblies.Execute()
   --- End of inner exception stack trace ---
   at Xamarin.Android.Diagnostic.Error(Int32 code, Exception innerException, String message, Object[] args)
   at Xamarin.Android.Tasks.LinkAssemblies.Execute()
   at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
   at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext() GimcoIOT.Andriod

答案 3 :(得分:1)

首先通过检查SUM(V)是否为正,确定行是正数还是负数。然后确定最小值或最大值是否等于其他行的SUM,通过从SUM(V)减去MIN(V)如果为负,或MAX(V)如果为正:

DELETE t 
FROM Test t
INNER JOIN (
    SELECT
        T, 
        SUM(V) - CASE WHEN SUM(V) >= 0 THEN MAX(V) ELSE MIN(V) END AS ToDelete
    FROM Test 
    GROUP BY T
    HAVING COUNT(*) >= 3
) a
    ON a.T = t.T
    AND a.ToDelete = t.V

ONLINE DEMO

答案 4 :(得分:1)

您可以使用以下查询来获取所需的输出: -

select * into #t1 from test

select * from
(
select TT.T as T,TT.V as V
from  test TT
JOIN
(select T,max(abs(V)) as V from #t1 
group by T) P
on TT.T=P.T
where abs(TT.V) <> P.V

UNION ALL


select A.T as T,A.V as V from test A
JOIN(
select T,count(T) as Tcount from test
group by T
having count(T)=1) B on A.T=B.T
) X order by T

drop table #t1

答案 5 :(得分:1)

您正在寻找每个组的值,该值是所有组的其他值的总和。例如。 4(2,2,4)或-5(-5,-4,-1)。

这通常每组只有一条记录。但它可以是同一数字的多倍。以下是关系的例子:(0,0)或(-2,2,4,4),或(-2,-2,4,4,4)或(-10,3,3,3,3, 4)。

如您所见,您正在以任何方式查找等于该组总和的一半的值。 (当然。我们正在寻找n + n,其中一个n在一个记录中,另一个n是所有其他记录的总和。)

唯一的特例是当组中只有一个值为零时。我们当然不想删除。

这是一个无法处理关系的更新语句,但会删除所有最大值而不只是一个:

delete from test
where 2 * v =
(
  select case when count(*) = 1 then null else sum(v) end
  from test fullgroup
  where fullgroup.t = test.t
);

为了处理关系,你需要人工行号,以便只删除所有候选人的一条记录。

with candidates as
(
  select t, v, row_number() over (partition by t order by t) as rn
  from
  (
    select 
      t, v, 
      sum(v) over (partition by t) as sumv, 
      count(*) over (partition by t) as cnt
    from test
  ) comparables
  where sumv = 2 * v and cnt > 1
) 
delete
from candidates
where rn = 1;

SQL小提琴:http://sqlfiddle.com/#!6/6d97e/1

答案 6 :(得分:0)

查看以下查询是否有帮助:

DELETE [Audit].[dbo].[Test] FROM [Audit].[dbo].[Test] as AA
INNER JOIN (select T, 
      CASE 
          WHEN MAX(V) < 0 THEN MIN(V) 
          WHEN MIN(V) > 0 THEN MAX(V) ELSE MAX(V)
      END as MAX_V,
      CASE 
          WHEN SUM(V) > 0 THEN  SUM(V) - MAX(V)
          WHEN SUM(V) < 0 THEN  SUM(V) - MIN(V) ELSE SUM(V)
      END as SUM_V_REST
      from [Audit].[dbo].[Test] 
      Group by T 
      Having Count(V) > 1) as BB ON AA.T = BB.T and AA.V = BB.MAX_V