SQL实现数据透视效果

一、透视

在SQL中实现类似Excel中数据透视表的效果,需要使用到PiVOT函数

SELECT <non-pivoted column>,
    [first pivoted column] AS <column name>,
    [second pivoted column] AS <column name>,
    ...
FROM
    (<SELECT query that produces the data>)
    AS <alias for the source query>
PIVOT
(
    <aggregation function>(<column being aggregated>)
    FOR
    [<column that contains the values that will become column headers>]
    IN ( [first pivoted column], [second pivoted column],
    ... [last pivoted column])
) AS <alias for the pivot table>

其中, 是不需要进行透视的列,[first pivoted column]、[second pivoted column] 等是需要进行透视的列, 是透视后新表格的列名, 是聚合函数,用于将多行数据聚合成一行数据, 是需要进行聚合的列,[] 是包含新列名的列名,IN 后面的括号中是新表格的列名。
实例数据

用透视函数,把日期打标的枚举值放在列上

select * from 

  (SELECT  
CASE WHEN DATEDIFF(DAY,日期,GETDATE())=1 THEN 'T-1' 
 WHEN DATEDIFF(DAY,发货日期,GETDATE())=2 THEN 'T-2' 
 WHEN DATEDIFF(DAY,发货日期,GETDATE())=3 THEN 'T-3'  END AS 日期打标
,[客户名称]
,[订单量]
  FROM [XX表]
) a 
  
  PIVOT(sum(订单量) for [日期打标] in([T-1],[T-2],[T-3])) as p 

2、动态列名

如果是我们希望动态的设置列名,列名取自某一列的枚举值(去重),可以拼接一个动态查询语句

DECLARE @cols AS NVARCHAR(MAX), @query AS NVARCHAR(MAX);

---拼接查询语句-----
SELECT @cols = STUFF(
    (
        SELECT DISTINCT ', [' + 日期 + ']'
        FROM [XX表]
        ORDER BY 1 --ORDER BY 1 表示按照查询结果中的第一列进行排序---
        FOR XML PATH('')--拼接查询结果
    ), 1, 2, ''-------将拼接结果最前面的第一个‘,’替换为''(删除最前面的逗号和空格)
);
select @cols

----定义一个查询,把列名套进去
SET @query = '
SELECT *
FROM (
    SELECT DATEPART(year, date_column) AS sales_year, DATEPART(month, date_column) AS sales_month, sales_amount
    FROM Sales
) AS sales_data
---使用透视函数----
PIVOT (
    SUM(sales_amount)
    FOR sales_month IN (' + @cols + ')
) AS pivot_table
ORDER BY sales_year;
';

EXECUTE(@query);

上面拼接过程用到两个函数

  1. STUFF函数:
    该函数的作用是替换指定字符串的一部分。其语法为:
SELECT STUFF( string_expression, start, length, replacement_string )

其中,string_expression是要替换的字符串,start是替换的起始位置,length是要替换的长度,replacement_string是替换后的新字符串。
以下是一个简单的示例:
假设有一个字符串 “Hello, World!”,我们想要将其中的 “World” 替换成 “Universe”,可以使用 STUFF 函数来实现:

SELECT STUFF('Hello, World!', 8, 5, 'Universe')

该语句的执行结果为 “Hello, Universe!”,其中,8 表示要替换的起始位置,5 表示要替换的长度,‘Universe’ 是替换后的新字符串。

  1. FOR XML PATH(’ ')函数:
    该函数的作用是将查询结果转化为XML格式,并将每一行的结果用拼接成一个字符串。其语法为:
SELECT column_name
FROM table_name
FOR XML PATH('')

其中,column_name是要拼接的列名,table_name是要查询的表名,PATH(‘’)表示不指定XML路径,直接将结果拼接成一个字符串。

这两个函数在SQL查询中非常有用,常用于将查询结果按照一定的格式进行拼接和替换。在上面的例子中,STUFF函数和FOR XML PATH(‘’)函数一起使用,将查询结果中的日期列取出来,按照一定的格式拼接成一个字符串,并赋值给变量@cols。

3、逆透视

UNPIVOT逆透视的作用和透视相反,用法相似,这里就不多赘述了。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQL+数据透视+VBA 使数据透视走向更灵活,更智能,更适用。 这个是我和师傅一撇首度合作,他提供了文件并提出了要求,我帮他实现效果 下面从几个方面解释一下: 1、功能 一个源文件和一个通过用SQL查询生成的数据透视 将源文件拖到电脑的任意位置,甚至将文件名也改掉,用VBA配上代码和窗体找到文件,数据透视仍然能够正常工作 2、套用 现在来讲讲怎么使做出来的东东适应大家的需要 2、1 用OLE DB窗口引用工作或写SQL语句,因为用这个方法同VBA相通,copy下来代码区的的语句 2、2 打开透视文件,将透视中的字段全部拖出来,也就是变成一个空数据透视。 右击下面工作图标 或者 工具》宏》visual basic 编辑器,点击模块看到代码区 2、3 将2、1步骤copy的语句commandtext的数据Array中的引号中 .CommandText = Array(" ") 可能不同版本会有一些差别,同时SQL语句中如果添加了文本生成新字段,双引号要成对翻倍 如:"出库" AS 单选项 要改成 ""出库"" AS 单选项 2、4 语句太长的处理:在代码区如果你想好看一些,你可以插入“ _”来换行,当然不能插在一个单词或自动名等中间。 2、5 将文件存盘,重新打开就会有了数据,你可以将字段拖入数据透视中,创建你自己的数据透视, 2、6 这样文件就可以使用,相信VBA的引导不用教就可以交给别人使用了 下面附上代码,包含3个区: 1、 工作簿去,打开文件时工作 Private Sub Workbook_Open() Dim OP If Dir(Sheets("path").Range("A1")) = "" Then OP = MsgBox("源文件已被移走,请选择下列选项" + Chr(10) + "1、选择是,重新输入文件全名" + Chr(10) + "2、选择否,打开原有的数据透视" + Chr(10) + "3、选择取消,关闭文件", vbYesNoCancel, "Scarlett温馨提示") If OP = vbYes Then UserForm1.Show End If If OP = vbNo Then ActiveWorkbook.Close True End If If OP = vbCancel Then Exit Sub End If Else Call refreshpv End If End Sub 2、窗体区,实现文件的查找 Private Sub CommandButton1_Click() Dim fopen As FileDialog Set fopen = Application.FileDialog(msoFileDialogFilePicker) fopen.Show TextBox1.Value = fopen.SelectedItems(1) Set fopen = Nothing End Sub Private Sub CommandButton2_Click() If InStr(TextBox1.Value, ".") > 0 Then Sheets("path").Range("A1") = TextBox1.Value Call refreshpv unload me Else MsgBox "文件名要带路径含后缀的文件名", "Scarlett_88温馨提示" TextBox1.SetFocus End If End Sub Private Sub CommandButton3_Click() Unload Me End Sub Private Sub TextBox1_Change() End Sub Private Sub UserForm_Activate() End Sub Private Sub UserForm_Click() TextBox1.Value = Sheets("path").Range("A1") End Sub 3、模块区,实现SQL语句的地址更新和刷新数据透视数据源 Sub refreshpv() With ActiveSheet.PivotTables("数据透视1").PivotCache .Connection = Array( _ "OLEDB;Provider=Microsoft.Jet.OLEDB.4.0;User ID=Admin;Data Sourc
MS Query基础语法讲解: 一、单查询 单查询是指仅涉及一个的查询 1、查询指定列 例1、查询材料进货明细中的定额名称及规格 SELECT 定额名称,规格 FROM [材料进货明细$] 注意:在excel中,一个工作示是这样的:[工作名称$] select的意思是:查询 上面那一句SQL语句的意思就是:从材料进货明细中取出定额名称及规格的值 例2、查询材料进货明细的详细记录 SELECT * FROM [材料进货明细$] 等价于: SELECT 序号, 定额名称,规格,日期,单位,数量 FROM [材料进货明细$] 注意:*的用法 2、查询经过计算的值 例3、查询材料进货明细的定额名称、规格、年份及数量 SELECT 定额名称,规格,year(日期) as 年份,数量 FROM [材料进货明细$] 注意:里面的年份已经通过了计算的了,成为一个新的变量。 加多一列自定义的列A厂: SELECT “A厂” ,定额名称,规格,year(日期) as 年份,数量 FROM [材料进货明细$] SELECT “A厂” as 工厂 ,定额名称,规格,year(日期) as 年份,数量 FROM [材料进货明细$] 比较一下上面两句SQL语句的区别,没有as 工厂与有as 工厂的区别 二、选择中若干元组 1、消除取重复的行 例4、查询材料进货明细的定额名称 SELECT 定额名称 FROM [材料进货明细$] 该查询结果会包含很多重复的行。消除重复行的话,必须指定关键词 distinct SELECT distinct 定额名称 FROM [材料进货明细$] 2、查询满足条件的元组 例5、查询材料进货明细中单位为“套”的所有记录 SELECT * FROM [材料进货明细$] where 单位= ‘套’ 本句语句中,要学会where的用法: 要查询满足指定条件的元组,可以通过where子句实现。where子句查询条件是: 比较: =,>,<,>=,<=,!=,<>,!>,!<;not +上述比较运算符 确定范围: between and ,not between and 确定集合:in,not in 字符匹配:like,not like 空值:is null,is not null 多重条件:and,or,not 例6、查询材料进货明细中数量在50—100之间的所有记录 SELECT * FROM [材料进货明细$] where 数量 between 50 and 100 如果是不在50-100之间的话,直接改成: SELECT * FROM [材料进货明细$] where 数量 not between 50 and 100 例7、查询材料进货明细中单位为“只”或“支”的所有记录 SELECT * FROM [材料进货明细$] where 单位 in(‘只’,'支’) 3、字符匹配 可以用like来实现,通配符%和_ a、%代任意长度的字符串,如a%b示以a开头,以b结尾的任意的字符串 b、_代任意单个字符 例8、查询材料进货明细中定额名称以“天津”开头的所有记录 SELECT * FROM [材料进货明细$] where 定额名称 like ‘天津%’ 例9、查询材料进货明细中定额名称以“天津”开头且字符为4个的所有记录 SELECT * FROM [材料进货明细$] where 定额名称 like ‘天津__’ 例10、查询材料进货明细中定额名称不以“天津”开头的所有记录 SELECT * FROM [材料进货明细$] where 定额名称 not like ‘天津%’ 4、涉及空值的查询 主要是以:null出现 例11、查询材料进货明细中规格为空的的所有记录 SELECT * FROM [材料进货明细$] where 规格 is null 5、多条件查询 例12、查询材料进货明细中定额名称为“天津三通”的并且数量大于30的所有记录 SELECT * FROM [材料进货明细$] where 定额名称 = ‘天津三通’ and 数量>30 三、order by 子句 desc(降序)、asc(升序) 例13、查询材料进货明细中数量大于30的所有记录,并且要按照数量来降序排列。 SELECT * FROM [材料进货明细$] where 数量>30 order by 数量 desc 四、聚集函数 count(distinct/all 列名):统计元组个数 sum:求和 avg:求平均值 max:最大值 min:最小值 例14、查询材料进货明细中天津大小头的最大数量。 SELECT max(数量) FROM [材料进货明细$] where 定额名称 = ‘天津大小头’ 或:SELECT max(数量) as 最大数量 FROM [材料进货明细$] where 定额名称 = ‘天津大小头’ 2. Excel源数据及分析下载:Excel数据透视教程:分类百分比 SQL语句: select *, Hz1.分类销量/Hz2.分类销量 as 分类百分比 from (select 品种,分公司, sum(数量) as 分类销量 from [数据$] group by 品种,分公司) Hz1, (select 分公司, sum(数量) as 分类销量 from [数据$] group by 分公司) Hz2 where hz1.分公司=Hz2.分公司 SQL语句解释: select 品种,分公司, sum(数量) as 分类销量 from [数据$] group by 品种,分公司 实现对品种、分公司两字段分组的统计求和 select 分公司, sum(数量) as 分类销量 from [数据$] group by 分公司 实现对分公司字段分组的统计求和 对分公司分组统计求和数是对品种、分公司两字段分组统计求和项目再对不同品种的总就和,也就是后者包含前者。 整句语句的意思就是,将两个查询结果作为新的查询分别命名为Hz1、Hz2,用 ”where hz1.分公司=Hz2.分公司“来组合数据, 没有条件的制约的话,将统计的结果再进行除数运算, 各品种的分组统计数(分组含品种字段)除以各品种已求和了的分组统计数(分组不含品种字段)求得所占比率, 最后在字段单元格设置为百分数就可以了。 3 在Excel中使用MS Query查询外部数据库的内容的优点是:不用设置公式、编写VBA代码、源数据库不用打开。 但要注意:源数据库的记录要有字段名,由于设置查询时的路径固定,。 因此源数据库文件不能随意移动(如确实要移动可以通过手工修改查询或VBA解决) 以下示例采用MS Query在“查询”工作簿中查询关闭的“销售”工作簿中sheet1的指定 “店铺”和指定“颜色”的内容(sheet1有“店铺”、“数量”、“颜色”等字段名及若干数据)。 操作前请先确定是否安装有MS Query。附上举例文件,请解压到D盘根目录下: 销售.xls为源数据,查询.xls中设置了msquery查询。 下载:MS Query查询未打开工作簿的内容例子 1、 新建一个工作,选择菜单【数据】—【导入外部数据】—【新建数据库查询】, 界面如图,由于查询excel数据库的内容,因此选择【Excel Files*】并确定; 2、 弹出〖选择工作簿〗对话框,选择“销售”工作簿,〖确定〗; 3、 弹出〖选择列〗对话框,如果此时弹出“没用内容”,确定后在〖选项〗中将“系统”勾上。 将所选工作簿的各个工作及工作中的字段名添加到查询结果中,全选可直接将工作名添加, 〖下一步〗〖下一步〗,选择“在MS query中继续编辑查询”; 4、 弹出MS Query查询编辑,点击【显示/隐藏条件】图标,在“条件字段”中添加“店铺”, 值改为“[店]”(方括号中内容随意),再添加个条件为“颜色”,值改为“[色]”,点击【将数据返回Excel】 5、 回到excel的“导入数据”对话框,点击〖参数〗,选中“店”字段,再选择“从下列单元格中获取数据”, 选择一个用来更改查询关键字的单元格(如B1),并勾选“单元格值更改时自动刷新”, “色”字段改成从单元格“B2”中获取,〖确定〗。数据放置位置选择“A3”。〖确定〗。 6、 当更改B1和B2单元格的内容(做个数据有效性)时,A3及以下的数据会即时刷新。 此法对于需要经常在局域网中查询数据非常方便,比如:数据放在局域网内的一台主机上,通过MS Query即可不打开工作簿查询数据
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值