ExcelTip.Net留存知识帖 ---【注:附件之前被网盘供应商清空后,现已修复-现已修复-现已修复为本地下载!】
现在位置:首页 > E文精选 > SQL in Excel > Excel中的SQL中交叉表查询中的累计

Excel中的SQL中交叉表查询中的累计

作者:绿色风 分类: 时间:2022-08-17 浏览:138
楼主
wise
本文来自ACMAIN_CHM的作品改编.

交叉表查询无疑有使用中可以很方便的进行数据的分析处理。你可以通过向导来生成(在向导中你可以选择是否生成行合计)或者直接按照这个Excel(ACCESS也适用)特有JET-SQL语法来写这个SQL语句。
TRANSFORM合计函数
    selectstatement
    TRANSFORM aggfunction
selectstatement
PIVOT pivotfield [IN (value1[, value2[, ...]])]

比如现有表 table3, 数据如下

 

可以用向导得到一个每人的成绩表如下

 
它对应的SQL语句如下:
  1. TRANSFORM Sum(Table3.Score) AS ScoreOfSum
  2. SELECT Table3.sName, Table3.sClass, Sum(Table3.Score) AS [Total Of Score]
  3. FROM Table3
  4. GROUP BY Table3.sName, Table3.sClass
  5. PIVOT Table3.Course;
关于这个SQL语句的说明,你可以自已查阅一下ACCESS自带的帮助手册中的详细说明,Excel里面的SQL也是参考Access的写法。
如果你想控制科目的显示顺序,可以试一下这个语法的作用。PIVOT pivotfield [IN (value1[, value2[, ...]])]
以上是交叉表查询的常见用法。美中不足,这个由向导生成的查询虽然有了行合计,但没有列合计。由于TRANSFORM 自身功能的限制无法直接生成列合计运算(我们这里所说的合计运算包括平均/最大/最小等,以下均不再说明)。但我们可以通过UNION联合来实现。
思路:直接在table3的数据中追加上合计行然后再进行交叉。
比如如果table3的数据能形成如下记录

 
这样我们就可以利用 TRANSFORM 来实现了。
1. 生成合计,你可以通过向导或自己生成这个合计的查询
  1. select course,avg(score)
  2. from table3
  3. group by course

 
2. 利用UNION生成交叉表查询的数据源。(这里我们用了UNION ALL,关于UNION的语法说明请自行查阅帮助,同样我们利用 'Total' as sName,null as sClass 生成了两个常数列以保证UNION的两个集合的列数相匹配。)
  1. select sName,sClass,Course,Score
  2. from Table3
  3. union all
  4. select 'Total' as sName,null as sClass,course,avg(score)
  5. from table3
  6. group by course

 

3. 把这个查询代入到一开的那个交叉查询中,替代原来的table3.
把把所有的table3. 换成 t. 如下

  1. TRANSFORM Sum(t.Score) AS ScoreOfSum
  2. SELECT t.sName, t.sClass, Sum(t.Score) AS [Total Of Score]
  3. FROM Table3
  4. GROUP BY t.sName, t.sClass
  5. PIVOT t.Course;
然后再把 from table3 变成
  1. TRANSFORM Sum(t.Score) AS ScoreOfSum
  2. SELECT t.sName, t.sClass, Sum(t.Score) AS [Total Of Score]
  3. FROM (select sName,sClass,Course,Score
  4.     from Table3
  5.     union all
  6.     select 'Total' as sName,null as sClass,course,avg(score)
  7.     from table3
  8.     group by course) t
  9. GROUP BY t.sName, t.sClass
  10. PIVOT t.Course;
结果如下


 
如果我们想再加上每个班的小计
那么就再union上每个班的合计平均值
  1. select 'subtotal' as sName,sClass,course,avg(score)
  2. from table3
  3. group by course,sClass
这样改为
  1. TRANSFORM Sum(t.Score) AS ScoreOfSum
  2. SELECT t.sName, t.sClass, Sum(t.Score) AS [Total Of Score]
  3. FROM (select sName,sClass,Course,Score
  4.     from Table3
  5.     union all
  6.     select 'subtotal' as sName,sClass,course,avg(score)
  7.     from table3
  8.     group by course,sClass
  9.     union all
  10.     select 'Total' as sName,null as sClass,course,avg(score)
  11.     from table3
  12.     group by course
  13. ) t
  14. GROUP BY t.sName, t.sClass,(t.sClass='subtotal'),(t.sClass='Total')
  15. order by (t.sClass='Total') desc,(t.sClass='subtotal') desc,sClass
  16. PIVOT t.Course
上面用了 order by (t.sClass='Total') desc,(t.sClass='subtotal') desc,sClass 来控制排序,以把subtotal, total 放在最后。


 
结束语:
显然通过灵活的SQL语句设计我们可以实现多种需要有VBA程序中实现功能。在实际运用中我们需要在各种方案之间来平衡以找到最佳的应用。有时候用程序的效率比较好,有些时候用查询的比较方便,有些时候用EXCEL可能更容易。
2楼
学问者
又学了不少东西!谢谢。
3楼
zyh196712
谢谢!学了一点新知识。
4楼
xinger7
曲高和寡。我是学不了。捧个人场,
5楼
亡者天下
学习了

还没有完全吃透!
6楼
tsoyzm
交叉表查询还真不好懂
7楼
cam333
难懂阿

免责声明

有感于原ExcelTip.Net留存知识的价值及部分知识具有的时间限定性因素, 经与ExcelTip.Net站长Apolloh商议并征得其同意, 现将原属ExcelTip.Net的知识帖采集资料于本站点进行展示, 供有需要的人士查询使用,也慰缅曾经的论坛时代。 所示各个帖子的原作者如对版权有异议, 可与本人沟通提出,或于本站点留言,我们会尽快处理。 在此,感谢ExcelTip.Net站长Apolloh的支持,感谢本站点所有人**绿色风(QQ:79664738)**的支持与奉献,特此鸣谢!
------本人网名**KevinChengCW(QQ:1210618015)**原ExcelTip.Net总版主之一

评论列表
sitemap