--1.【行列转换】
--列转行
USE tempdb
GO
IF (OBJECT_ID('DEPT') IS NOT NULL)
DROP TABLE DEPT
CREATE TABLE DEPT(NAME VARCHAR(5),COL1 INT,COL2 INT,COL3 INT,COL4 INT,COL5 INT,COL6 INT)
INSERT INTO DEPT
SELECT 'A',10,50,20,30,0,80
UNION ALL
SELECT 'B',50,20,10,10,20,40
UNION ALL
SELECT 'C',5,0,0,10,0,80
SELECT * FROM DEPT
select NAME,NEWCOLUMNS,value
--into #TEMP
from DEPT
unpivot(
value for NEWCOLUMNS in(COL1,COL2,COL3,COL4,COL5,COL6)
) as t
/*
NAME NEWCOLUMNS value
A COL1 10
A COL2 50
A COL3 20
A COL4 30
A COL5 0
A COL6 80
B COL1 50
B COL2 20
B COL3 10
B COL4 10
B COL5 20
B COL6 40
C COL1 5
C COL2 0
C COL3 0
C COL4 10
C COL5 0
C COL6 80
*/
--行转列
select * from #TEMP
select * from #TEMP
PIVOT(
max(value) for NEWCOLUMNS in(COL1,COL2,COL3,COL4,COL5,COL6)
) as t
/*
NAME COL1 COL2 COL3 COL4 COL5 COL6
A 10 50 20 30 0 80
B 50 20 10 10 20 40
C 5 0 0 10 0 80
*/
--2.【每行中的数值统计:每行中各列数据的最大值、最小值、平均值】
USE tempdb
GO
IF (OBJECT_ID('DEPT') IS NOT NULL)
DROP TABLE DEPT
CREATE TABLE DEPT(NAME VARCHAR(5),COL1 INT,COL2 INT,COL3 INT,COL4 INT,COL5 INT,COL6 INT)
INSERT INTO DEPT
SELECT 'A',10,50,20,30,0,80
UNION ALL
SELECT 'B',50,20,10,10,20,40
UNION ALL
SELECT 'C',5,0,0,10,0,80
SELECT *
,MaxValue=(select MAX(COL) FROM (
SELECT COL1 AS COL
UNION ALL
SELECT COL2
UNION ALL
SELECT COL3
UNION ALL
SELECT COL4
UNION ALL
SELECT COL5
UNION ALL
SELECT COL6 ) A)
,MINValue=(select MIN(COL) FROM (
SELECT COL1 AS COL
UNION ALL
SELECT COL2
UNION ALL
SELECT COL3
UNION ALL
SELECT COL4
UNION ALL
SELECT COL5
UNION ALL
SELECT COL6 ) B)
,AVGValue=(select AVG(COL) FROM (
SELECT COL1 AS COL
UNION ALL
SELECT COL2
UNION ALL
SELECT COL3
UNION ALL
SELECT COL4
UNION ALL
SELECT COL5
UNION ALL
SELECT COL6 ) c)
FROM DEPT
/* 结果:
NAME COL1 COL2 COL3 COL4 COL5 COL6 MaxValue MINValue AVGValue
A 10 50 20 30 0 80 80 0 31
B 50 20 10 10 20 40 50 10 25
C 5 0 0 10 0 80 80 0 15
*/
--3.【每列中的数值统计】
USE tempdb
GO
IF (OBJECT_ID('DEPT') IS NOT NULL)
DROP TABLE DEPT
CREATE TABLE DEPT(ID INT IDENTITY (1,1),VALUE INT)
INSERT INTO DEPT(VALUE)
VALUES(90),(86),(60),(80),(100),(0),(0),(85),(80),(65)
SELECT * FROM DEPT
select ID,VALUE
,id = dense_rank() over(order by VALUE desc)
,比例 = VALUE*100.0/sum(VALUE)OVER()
,最大差值 = max(VALUE)OVER() - VALUE
,最小差值 = VALUE - min(VALUE)OVER()
from DEPT
/*结果:
ID VALUE id 比例 最大差值 最小差值
5 100 1 15.479876160990 0 100
1 90 2 13.931888544891 10 90
2 86 3 13.312693498452 14 86
8 85 4 13.157894736842 15 85
9 80 5 12.383900928792 20 80
4 80 5 12.383900928792 20 80
10 65 6 10.061919504643 35 65
3 60 7 9.287925696594 40 60
6 0 8 0.000000000000 100 0
7 0 8 0.000000000000 100 0
*/
--4.【某部门的所有上级机构或下级机构】
IF (OBJECT_ID('DEPT') IS NOT NULL)
DROP TABLE DEPT
CREATE TABLE DEPT(ID INT,PID INT, NAME VARCHAR(20))
INSERT INTO DEPT VALUES
(1,0,'总公司'),
(2,1,'研发部'),
(3,1,'销售部'),
(4,1,'财务部'),
(5,2,'研发一部'),
(6,2,'研发二部'),
(7,3,'销售一部'),
(8,3,'销售二部'),
(9,3,'销售三部'),
(10,5,'小组A'),
(11,5,'小组B')
SELECT * FROM DEPT
--求一个部门的所有下级,如[研发部] 的所有下级'
--条件:所有部门的父id都等于[研发部]的ID,取到都是下级的
;WITH D(ID,PID,NAME,LVL)
AS(
SELECT ID,PID,NAME,0 LVL FROM DEPT WHERE NAME='研发部'
UNION ALL
SELECT DEPT.ID,DEPT.PID,DEPT.NAME,LVL +1
FROM DEPT INNER JOIN D ON DEPT.PID=D.ID
)
SELECT * FROM D
--求一个部门的所有上级,如[研发一部] 的所有上级'
;WITH D(ID,PID,NAME,LVL)
AS(
SELECT ID,PID,NAME,0 LVL FROM DEPT WHERE NAME='研发一部'
UNION ALL
SELECT DEPT.ID,DEPT.PID,DEPT.NAME,LVL +1
FROM DEPT INNER JOIN D ON DEPT.ID=D.PID
)
SELECT * FROM D
SELECT * FROM DEPT INNER JOIN (SELECT ID,PID,NAME FROM DEPT WHERE NAME='研发部' ) TAB ON DEPT.ID=TAB.ID
--5.【添加 删除 更新 时取出数据】
drop table #temp
SELECT * FROM DEPT --继续用上一步的表
SELECT NAME into #temp FROM DEPT WHERE 1<>1
SELECT * FROM #temp
insert into #temp(NAME)
output inserted.NAME --into tableName(colName) 输出可插入到其他表
SELECT NAME FROM DEPT
Delete DEPT
output deleted.NAME
where PID = 3
UPDATE #temp
SET NAME = '集团'
OUTPUT Inserted.NAME Old, Deleted.NAME New
WHERE NAME = '总公司'
--6.【Merge into】
/*
drop table #a;
drop table #b;
*/
create table #a (aid int null,aname varchar(10) null);
create table #b (bid int null,bname varchar(10) null);
insert into #a values(1,'Value1');
insert into #a values(3,'Value3');
insert into #a values(4,'Value4');
insert into #b values(1,'New Value1');
insert into #b values(2,'New Value2');
insert into #b values(3,'New Value3');
merge into #a using #b
on #a.aid=#b.bid
when matched --and #a.aid = 1 (可增加条件)
then update set #a.aname=#b.bname
when not matched
then insert values(#b.bid,#b.bname)
when not matched by source then
delete; --必须分号结束
select * from #a;
select * from #b;
--7.【多列查询同一值简化】
select * from tableName
where COL1=100 or COL2=100 or COL3=100 or COL4=100 or COL5=100 or COL6=100
--简化操作
select * from tableName where 100 in(COL1,COL2,COL3,COL4,COL5,COL6)
--8.【同列字符相连】
use tempdb
go
-- drop table tb
create table tb(id int,value varchar(30))
go
insert into tb
values
(1,'aa'),
(1,'bb'),
(2,'aaa'),
(2,'bbb'),
(2,'ccc')
select * from tb
SELECT DISTINCT id,STUFF((SELECT ','+value FROM tb B WHERE A.id=B.id FOR XML PATH('')),1,1,'') AS value
FROM tb A
/*结果:
id value
--- -----------
1 aa,bb
2 aaa,bbb,ccc
*/
--逆转换
use tempdb
go
-- drop table tb
create table tb(id int,value varchar(30))
go
insert into tb values(1,'aa,bb')
insert into tb values(2,'aaa,bbb,ccc')
select * from tb
select A.id, B.value
from(
select id, [value] = convert(xml,' <root> <v>' + replace([value], ',', ' </v> <v>') + ' </v> </root>') from tb
)A
outer apply(
select value = N.v.value('.', 'varchar(100)') from A.[value].nodes('/root/v') N(v)
)B
/*结果:
id value
-- -----
1 aa
1 bb
2 aaa
2 bbb
2 ccc
*/
--8.【同列数值分组累加】
drop table #temp
create table #temp(name varchar(1),value int)
insert #temp
select 'a',1 union all
select 'b',5 union all
select 'a',3 union all
select 'a',5 union all
select 'b',9 union all
select 'b',5
select * from #temp
;with tabA as(
select row_number() over(partition by name order by name) id,name,value from #temp
)
, tabB AS(
select id,name,value,value as total from tabA WHERE id = 1
union all
select a.id,a.name,a.value,a.value+b.total
from tabA a inner join tabB b on a.name=b.name and a.id=b.id+1
)
select * from tabB order by name,id
/*结果:
id name value total
-- ---- ----- ----
1 a 3 3
2 a 5 8
3 a 1 9
1 b 5 5
2 b 9 14
3 b 5 19
*/
--【一条sql语句执行N次】
CREATE TABLE TB(ID INT IDENTITY (1,1),NAME VARCHAR(40))
INSERT INTO TB(NAME) SELECT 'KK'+CONVERT(VARCHAR(5),isnull(@@IDENTITY,0)+1)
GO 10
--【随机取出N条记录】
select top 5 * from tableName order by newid()
年内按月累计(如:2月累计为前两个月的,3月累计为前三个月的)
CREATE TABLE T (tDate DATETIME,tValue INT)
INSERT INTO dbo.T
SELECT '2017-01-08',10 UNION
SELECT '2017-01-25',20 UNION
SELECT '2017-02-11',30 UNION
SELECT '2017-02-28',40 UNION
SELECT '2017-03-17',50 UNION
SELECT '2017-04-03',60 UNION
SELECT '2017-04-20',70 UNION
SELECT '2017-05-07',80 UNION
SELECT '2017-05-24',90
SELECT * FROM dbo.T;
SELECT MONTH(tDate) AS 月份,
(SELECT SUM(tValue) FROM dbo.T T1 WHERE MONTH(T1.tDate)<=MONTH(T.tDate)) 累计
FROM dbo.T
GROUP BY MONTH(tDate)
tDate tValue
----------------------- -----------
2017-01-08 00:00:00.000 10
2017-01-25 00:00:00.000 20
2017-02-11 00:00:00.000 30
2017-02-28 00:00:00.000 40
2017-03-17 00:00:00.000 50
2017-04-03 00:00:00.000 60
2017-04-20 00:00:00.000 70
2017-05-07 00:00:00.000 80
2017-05-24 00:00:00.000 90
(9 行受影响)
月份 累计
----------- -----------
1 30
2 100
3 150
4 280
5 450
(5 行受影响)
求x个月内产品逐月库存
if object_id('[huang]') is not null drop table [huang]
go
create table [huang]([年] int,[月] int,[产品] varchar(1),[未出库数量] int)
insert [huang]
select 2013,11,'A',100 union all
select 2014,1,'A',300 union all
select 2013,10,'B',1000 union all
select 2013,11,'B',1500 union all
select 2013,12,'B',3001
--------------开始查询--------------------------
;WITH d AS
(
SELECT CONVERT(VARCHAR(10),DATEADD(mm,number,'2013-11-01'),120)[date],b.产品
FROM master..spt_values cross JOIN (SELECT DISTINCT 产品 FROM [huang]) b
WHERE [type]='p' AND number>0 AND number<7 --这个7可以控制月份
),cte AS (
select ISNULL([年],YEAR(d.[date])) [年],ISNULL([月],month(d.[date])) [月],ISNULL(a.[产品],d.产品) 产品,ISNULL([未出库数量],0)[未出库数量],ROW_NUMBER()OVER(PARTITION BY ISNULL(a.[产品],d.产品) ORDER BY ISNULL([年],YEAR(d.[date])),ISNULL([月],month(d.[date]))) id
from [huang] a full JOIN d ON a.[年]=YEAR(d.[date]) AND a.[月]=MONTH(d.[date]) AND a.[产品]=d.产品
)
SELECT [年],[月],[产品],ISNULL((SELECT SUM([未出库数量] ) FROM cte b WHERE a.id>b.id AND a.[产品]=b.[产品]),0)[未出库数量]
FROM cte a
ORDER BY [产品],[年],a.月
/*
年 月 产品 未出库数量
----------- ----------- ---- -----------
2013 11 A 0
2013 12 A 100
2014 1 A 100
2014 2 A 400
2014 3 A 400
2014 4 A 400
2014 5 A 400
2013 10 B 0
2013 11 B 1000
2013 12 B 2500
2014 1 B 5501
2014 2 B 5501
2014 3 B 5501
2014 4 B 5501
2014 5 B 5501
*/