具有分组和未分组总和的MS Excel SQL查询

时间:2018-04-17 12:05:43

标签: sql excel excel-vba vba

我正在使用VBA宏并尝试对Excel工作表中的表执行查询。我的查询以所有文本字段和布尔字段的简单选择开头。我需要它们之间的所有可能的组合,以及它们的总和。我的表(缩写)看起来像

Txt1    Txt2    Txt3    Amt1    Amt2    Bool1   Bool2   Bool3
A       B          F    10      1000    YES     YES     YES
A       D          F    20       200    YES     YES     YES
A       B          F    5        100    YES     YES     YES
A       B          G    10      1200    NO      YES     NO
A       D          H    5       1300    NO      YES     NO
A       B          I    30       500    YES     YES     NO
A       B          J    10       600    YES     YES     YES
A       D          K    6        800    YES     YES     YES
A       B          F    4       1000    NO      YES     YES
A       B          F    2       2900    NO      YES     NO
A       D          F    6       3150    YES     YES     NO
A       B          F    1       3400    YES     YES     NO
A       B          F    0       3650    YES     YES     YES
A       D          F    5       3900    NO      YES     YES
A       B          H    15      4150    NO      YES     YES
A       B          F    2       4400    YES     YES     NO
A       D          F    1       4650    YES     YES     NO
A       B          F    5       4900    YES     YES     NO
A       B          G    6       5150    NO      NO      YES
A       D          H    8       5400    NO      NO      YES
A       B          I    2        100    YES     YES     YES

这是我使用此代码的地方:

SELECT DISTINCTROW [Txt1], [Txt2], [Txt3], [Bool1], [Bool2], [Bool3], Sum([Amt1]) AS [Sum Amt1], Sum([Amt2]) AS [Sum Amt2] 
FROM [mytable] 
GROUP BY [Txt1], [Txt2], [Txt3], [Bool1], [Bool2], [Bool3];

它有效:

Txt1   Txt2   Txt3   Bool1   Bool2   Bool3   Sum Amt1   Sum Amt2
    A     B     F     NO     YES     NO       2               2900
    A     B     F     NO     YES     YES      4               1000
    A     B     F     YES    YES     NO       8               12700
    A     B     F     YES    YES     YES      15              4750
    A     B     G     NO     NO      YES      6               5150
    A     B     G     NO     YES     NO       10              1200
    A     B     H     NO     YES     YES      15              4150
    A     B     I     YES    YES     NO       30              500
    A     B     I     YES    YES     YES      2               100
    A     B     J     YES    YES     YES      10              600
    A     D     F     NO     YES     YES      5               3900
    A     D     F     YES    YES     NO       7               7800
    A     D     F     YES    YES     YES      20              200
    A     D     H     NO     NO      YES      8               5400
    A     D     H     NO     YES     NO       5               1300
    A     D     K     YES    YES     YES      6               800

我真正需要的是一个字段/列,它对文本字段之间的每个组合进行求和,甚至更好地包含Bool字段的摘要行。如果我这样做:

SELECT DISTINCTROW [Txt1], [Txt2], [Txt3], Sum([Amt1]) AS [Sum Amt1], Sum([Amt2]) AS [Sum Amt2] 
FROM [mytable] 
GROUP BY [Txt1], [Txt2], [Txt3];

我摆脱了Bool字段并获得摘要,但案例是我不知道如何将两个查询放在一起。

Txt1   Txt2 Txt3    Sum Amt1    Sum Amt2
A       B      F       29      21350
A       B      G       16       6350
A       B      H       15       4150
A       B      I       32        600
A       B      J       10        600
A       D      F       32      11900
A       D      H       13       6700
A       D      K        6        800

我尝试在我的表中添加一个虚拟布尔列,并将虚拟字段添加到我的查询中(包括select和group指令),但它只是产生了一条错误消息(-2147217904,缺少参数)。 / p>

我怀疑我需要某种JOIN,但这显然超出了我对SQL的了解。有什么帮助吗?

[编辑]
这样的东西就可以了(参见SumGrouped字段):

Txt1   Txt2   Txt3   Bool1   Bool2   Bool3   Sum Amt1   Sum Amt2     SumGrouped
    A     B     F     NO     YES     NO       2               2900     21350
    A     B     F     NO     YES     YES      4               1000     21350
    A     B     F     YES    YES     NO       8               12700    21350
    A     B     F     YES    YES     YES      15              4750     21350
    A     B     G     NO     NO      YES      6               5150     6350
    A     B     G     NO     YES     NO       10              1200     6350
    A     B     H     NO     YES     YES      15              4150     4150
    A     B     I     YES    YES     NO       30              500      600
    A     B     I     YES    YES     YES      2               100      600
    A     B     J     YES    YES     YES      10              600      600
    A     D     F     NO     YES     YES      5               3900     11900
    A     D     F     YES    YES     NO       7               7800     11900
    A     D     F     YES    YES     YES      20              200      11900
    A     D     H     NO     NO      YES      8               5400     6700
    A     D     H     NO     YES     NO       5               1300     6700
    A     D     K     YES    YES     YES      6               800      800         

是的,现在我想知道使用数据透视表是否更容易

2 个答案:

答案 0 :(得分:0)

只需在主外部查询中加入两个查询即可。具体来说,使用您的两个聚合查询(其中DISTINCTROW是多余的)作为派生表(即FROMJOIN子句中的子查询),然后将它们连接到文本字段。

SELECT allagg.*, textagg.[Sum Amt2] AS SumGrouped
FROM
  (SELECT [Txt1], [Txt2], [Txt3], [Bool1], [Bool2], [Bool3],
          Sum([Amt1]) AS [Sum  Amt1], Sum([Amt2]) AS [Sum Amt2] 
   FROM [mytable] 
   GROUP BY [Txt1], [Txt2], [Txt3], [Bool1], [Bool2], [Bool3]) As allagg

INNER JOIN      
  (SELECT [Txt1], [Txt2], [Txt3],
          Sum([Amt1]) AS [Sum Amt1], Sum([Amt2])  AS [Sum Amt2] 
   FROM [mytable] 
   GROUP BY [Txt1], [Txt2], [Txt3]) As textagg

ON allagg.[Txt1] = textagg.[Txt1]
AND allagg.[Txt2] = textagg.[Txt2]
AND allagg.[Txt3] = textagg.[Txt3]

您可以添加 boolagg 作为第三个派生表。如果在MS Excel中运行SQL,您将使用Jet / ACE SQL方言,该方言需要在JOIN子句中包含超过2个表的括号。

SELECT allagg.*, textagg.[Sum Amt2] AS SumTxtGrouped, boolagg.[Sum Amt2] AS SumBoolGrouped
FROM
  ((SELECT [Txt1], [Txt2], [Txt3], [Bool1], [Bool2], [Bool3],
          Sum([Amt1]) AS [Sum  Amt1], Sum([Amt2]) AS [Sum Amt2] 
   FROM [mytable] 
   GROUP BY [Txt1], [Txt2], [Txt3], [Bool1], [Bool2], [Bool3]) As allagg

INNER JOIN      
  (SELECT [Txt1], [Txt2], [Txt3],
          Sum([Amt1]) AS [Sum Amt1], Sum([Amt2])  AS [Sum Amt2] 
   FROM [mytable] 
   GROUP BY [Txt1], [Txt2], [Txt3]) As textgg

ON allagg.[Txt1] = textagg.[Txt1]
AND allagg.[Txt2] = textagg.[Txt2]
AND allagg.[Txt3] = textagg.[Txt3])

INNER JOIN      
  (SELECT [Bool1], [Bool2], [Bool3],
          Sum([Amt1]) AS [Sum Amt1], Sum([Amt2])  AS [Sum Amt2] 
   FROM [mytable] 
   GROUP BY [Bool1], [Bool2], [Bool3]) As boolagg

ON allagg.[Bool1] = boolagg.[Bool1]
AND allagg.[Bool2] = boolagg.[Bool2]
AND allagg.[Bool3] = boolagg.[Bool3]

答案 1 :(得分:0)

我使用GROUP BY ROLLUP来获得您想要的结果。 GROUP BY ROLLUP中的列周围的括号定义了您感兴趣的分组集。所有六列的最低级别的详细信息组,仅3个txt列的下一个最低级别的详细信息组。最终的最小粒度级别汇总了所有记录。

SQL Fiddle

查询1

SELECT [Txt1], [Txt2], [Txt3]
     , [Bool1], [Bool2], [Bool3]
     , Sum([Amt1]) AS [Sum Amt1], Sum([Amt2]) AS [Sum Amt2] 
  FROM [mytable] 
 GROUP BY ROLLUP ( ([Txt1], [Txt2], [Txt3])
                 , ([Bool1], [Bool2], [Bool3]))
 ORDER BY grouping_id([txt1],[bool1])
     , [Txt1], [Txt2], [Txt3]
     , [Bool1], [Bool2], [Bool3]

<强> Results

|   Txt1 |   Txt2 |   Txt3 |  Bool1 |  Bool2 |  Bool3 | Sum Amt1 | Sum Amt2 |
|--------|--------|--------|--------|--------|--------|----------|----------|
|      A |      B |      F |     NO |    YES |     NO |        2 |     2900 |
|      A |      B |      F |     NO |    YES |    YES |        4 |     1000 |
|      A |      B |      F |    YES |    YES |     NO |        8 |    12700 |
|      A |      B |      F |    YES |    YES |    YES |       15 |     4750 |
|      A |      B |      G |     NO |     NO |    YES |        6 |     5150 |
|      A |      B |      G |     NO |    YES |     NO |       10 |     1200 |
|      A |      B |      H |     NO |    YES |    YES |       15 |     4150 |
|      A |      B |      I |    YES |    YES |     NO |       30 |      500 |
|      A |      B |      I |    YES |    YES |    YES |        2 |      100 |
|      A |      B |      J |    YES |    YES |    YES |       10 |      600 |
|      A |      D |      F |     NO |    YES |    YES |        5 |     3900 |
|      A |      D |      F |    YES |    YES |     NO |        7 |     7800 |
|      A |      D |      F |    YES |    YES |    YES |       20 |      200 |
|      A |      D |      H |     NO |     NO |    YES |        8 |     5400 |
|      A |      D |      H |     NO |    YES |     NO |        5 |     1300 |
|      A |      D |      K |    YES |    YES |    YES |        6 |      800 |
|      A |      B |      F | (null) | (null) | (null) |       29 |    21350 |
|      A |      B |      G | (null) | (null) | (null) |       16 |     6350 |
|      A |      B |      H | (null) | (null) | (null) |       15 |     4150 |
|      A |      B |      I | (null) | (null) | (null) |       32 |      600 |
|      A |      B |      J | (null) | (null) | (null) |       10 |      600 |
|      A |      D |      F | (null) | (null) | (null) |       32 |    11900 |
|      A |      D |      H | (null) | (null) | (null) |       13 |     6700 |
|      A |      D |      K | (null) | (null) | (null) |        6 |      800 |
| (null) | (null) | (null) | (null) | (null) | (null) |      153 |    52450 |

查询2 模拟ROLLUP:

SELECT [Txt1], [Txt2], [Txt3]
     , [Bool1], [Bool2], [Bool3]
     , Sum([Amt1]) AS [Sum Amt1], Sum([Amt2]) AS [Sum Amt2] 
  FROM [mytable] 
 GROUP BY [Txt1], [Txt2], [Txt3]
        , [Bool1], [Bool2], [Bool3]
UNION ALL
SELECT [Txt1], [Txt2], [Txt3]
     , NULL, NULL, NULL
     , Sum([Amt1]) AS [Sum Amt1], Sum([Amt2]) AS [Sum Amt2] 
  FROM [mytable] 
 GROUP BY [Txt1], [Txt2], [Txt3]
UNION ALL
SELECT NULL, NULL, NULL
     , NULL, NULL, NULL
     , Sum([Amt1]) AS [Sum Amt1], Sum([Amt2]) AS [Sum Amt2] 
  FROM [mytable]

<强> Results

|   Txt1 |   Txt2 |   Txt3 |  Bool1 |  Bool2 |  Bool3 | Sum Amt1 | Sum Amt2 |
|--------|--------|--------|--------|--------|--------|----------|----------|
|      A |      B |      F |     NO |    YES |     NO |        2 |     2900 |
|      A |      B |      F |     NO |    YES |    YES |        4 |     1000 |
|      A |      B |      F |    YES |    YES |     NO |        8 |    12700 |
|      A |      B |      F |    YES |    YES |    YES |       15 |     4750 |
|      A |      B |      G |     NO |     NO |    YES |        6 |     5150 |
|      A |      B |      G |     NO |    YES |     NO |       10 |     1200 |
|      A |      B |      H |     NO |    YES |    YES |       15 |     4150 |
|      A |      B |      I |    YES |    YES |     NO |       30 |      500 |
|      A |      B |      I |    YES |    YES |    YES |        2 |      100 |
|      A |      B |      J |    YES |    YES |    YES |       10 |      600 |
|      A |      D |      F |     NO |    YES |    YES |        5 |     3900 |
|      A |      D |      F |    YES |    YES |     NO |        7 |     7800 |
|      A |      D |      F |    YES |    YES |    YES |       20 |      200 |
|      A |      D |      H |     NO |     NO |    YES |        8 |     5400 |
|      A |      D |      H |     NO |    YES |     NO |        5 |     1300 |
|      A |      D |      K |    YES |    YES |    YES |        6 |      800 |
|      A |      B |      F | (null) | (null) | (null) |       29 |    21350 |
|      A |      B |      G | (null) | (null) | (null) |       16 |     6350 |
|      A |      B |      H | (null) | (null) | (null) |       15 |     4150 |
|      A |      B |      I | (null) | (null) | (null) |       32 |      600 |
|      A |      B |      J | (null) | (null) | (null) |       10 |      600 |
|      A |      D |      F | (null) | (null) | (null) |       32 |    11900 |
|      A |      D |      H | (null) | (null) | (null) |       13 |     6700 |
|      A |      D |      K | (null) | (null) | (null) |        6 |      800 |
| (null) | (null) | (null) | (null) | (null) | (null) |      153 |    52450 |