SQL以多种方式对相同数据进行分组

时间:2019-02-19 14:32:26

标签: sql sql-server tsql

我需要将数据分为多个组。每个分组都是数据的总和。但是,对于每个分组,如果某项是多个组的成员,而一个组被排除在外,则需要将该项目从其所属的任何其他组中删除。

例如:

CREATE TABLE #test (Item VARCHAR(1), Group1 BIT, Group2 BIT, Units INT)

INSERT INTO #test (Item, Group1, Group2, Units)
VALUES
('A', 1, 0, 2),
('B', 1, 1, 2),
('C', 1, 1, 2),
('D', 1, 1, 2),
('E', 0, 1, 2)

如果我们假设第1组要返回的总数为7,而第2组则需要返回的总数为9。

到目前为止,我已经拥有了:

--Everything that is NOT NULL will be excluded
Select *
FROM #test t
LEFT OUTER JOIN (
    SELECT t.Group1, SUM(t.Units) AS TotalUnits
    FROM #test t
    WHERE t.Group1 = 1
    GROUP BY t.Group1
    HAVING SUM(Units) < 7
) g1 ON g1.Group1 = t.Group1
LEFT OUTER JOIN (
    SELECT t.Group2, SUM(t.Units) AS TotalUnits
    FROM #test t
    WHERE t.Group2 = 1
    GROUP BY t.Group2
    HAVING SUM(Units) < 9
) g2 ON g2.Group2 = t.Group2

如果运行此命令,则会看到:

  

B,C,D,E未通过Group2的测试,因为它们总计8个单位,并且   他们必须至少为9。

     

A,B,C,D接替Group1,因为它们加起来最多为8个单位,   只需拥有7个或更多。

但是,我需要对此进行更改,以使两者均失败。

由于B,C,D在Group2中失败,因此需要将它们排除在Group1之外。

所以,实际上,Group1只能是A项,用于2个单位,这将失败,因为它小于group1所需的7个。

很难解释,但是基本上我需要将相同的数据以多种方式进行分组,因此,如果一次分组失败,则将其排除在第二次分组之外,反之亦然。

对于输出,我希望这样。请注意,Group1的总单位为2,因为B,C,D不再计入总和。从技术上讲,我认为Group2的TotalUnits也应该为2,因为当group1失败时,项目B,C,D不再可以计入其总和。基本上是试图同时评估两个组,其中一个的总和取决于另一个的总和。

Item    Group1  Group2  Units   Group1  TotalUnits  Group2  TotalUnits
A         1        0      2       1        2         NULL     NULL
B         1        1      2       1        2          1        8
C         1        1      2       1        2          1        8
D         1        1      2       1        2          1        8
E         0        1      2      NULL     NULL        1        8

2 个答案:

答案 0 :(得分:0)

我想您所需要的就是将其添加到查询的末尾:

where g1.Group1=1 and g2.Group2=1

请注意,您从子查询表中“绘制”了group1 / 2信息,当HAVING过滤掉子查询表时,它们将返回NULL。

还请注意,您提供的CREATE TABLE语句缺少带有零的第4列...

答案 1 :(得分:0)

这是您要寻找的吗?

select t.*
from (select t.*,
             sum(group1 * units) over () as group1_units,
             sum(group2 * units) over () as group2_units
      from #test t
     ) t
where (group1 = 1 and group1_units >= 7) or
      (group2 = 1 and group2_units >= 9);