五维思考

学习要加,骄傲要减,机会要乘,懒惰要除。 http://www.5dthink.cn

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

1.行列转换

--列转行
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
SELECT * FROM #TEMP 
/*
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 
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.每行中的数值统计:每行中各列数据的最大值、最小值、平均值

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.每列中的数值统计

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.某部门的所有上级机构或下级机构

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

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 
*/

9.同列数值分组累加

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
*/

10.一条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

11.随机取出N条记录

select top 5 * from tablename order by newid()

12.年内按月累计

如: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 T1WHERE 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 行受影响)
*/

13.求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
 */
posted on 2017-02-21 11:20  五维思考  阅读(197)  评论(0编辑  收藏  举报

QQ群:1. 全栈码农【346906288】2. VBA/VSTO【2660245】