SQL常用
2018-03-02 14:05 梦游0和1的世界 阅读(267) 评论(0) 编辑 收藏 举报SQL WITH CUBE 的用法 select [name],numb,sum(fenshu) from dbo.PeopleInfo group by [name],numb with cube 结果为下列语句的总和 select [name],numb,sum(fenshu) from dbo.PeopleInfo group by [name],numb select [name],sum(fenshu) from dbo.PeopleInfo group by [name] select numb,sum(fenshu) from dbo.PeopleInfo group by numb select sum(fenshu) from dbo.PeopleInfo WITH CUBE 为聚合字段的所有排列组合再加一列不聚合为总和的记录,SELECT 中不含有的字段值为NULL select [name],numb,sum(fenshu),grouping(numb) isaddtional from dbo.PeopleInfo group by [name],numb with rollup having grouping(numb)=1 grouping(numb) 列的值为一NUMB列 WITH CUBE 后 额外透视出的列 用法规律 SELECT EmployeeId,spdb_orgno,spdb_vipclass,GROUPING(EmployeeId),GROUPING(spdb_orgno),GROUPING(spdb_vipclass), SUM (spdb_countmonthbal) FROM [PCRM_REPORT].[dbo].[tb_VipContactBusiness] group by EmployeeId,spdb_orgno,spdb_vipclass with cube having GROUPING(EmployeeId)=1 and GROUPING(spdb_orgno)=1 and GROUPING(spdb_vipclass)=1 在统计时如果 如果要各自多列 看统计结果时 可以CUBE 一次得到, 拿需要的结果, HAVING GROUPING 对应规律即可 select base.org_number, base.account_number, GROUPING(base.account_number) as g1, COUNT(1) as cuscount, Sum(detail.Spdb_lastmonthbal) as productmonthbal, Sum(detail.spdb_monthavgbal9) as productmonthavg from pcrm_report.dbo.tb_PCRM_ReportBase base with(nolock) inner join pcrm_mscrm.dbo.spdb_proddetail detail with(nolock) on base.account_number = detail.Spdb_accountnumber where detail.Spdb_productnumber like '01%' and detail.spdb_monthavgbal9 >0 group by GROUPING sets ( base.org_number, (base.account_number,base.org_number) ) grouping set 更灵活, 比起GROUP BY UOION ALL 效率更高 ; WITH ShowSubDepartment(bid,subid, name) AS ( -- Anchor Member (AM) SELECT BusinessUnitId,ParentBusinessUnitId,DivisionName FROM PCRM_MSCRM.dbo.BusinessUnitBase WHERE DivisionName='980000' UNION ALL -- Recursive Member (RM) SELECT BusinessUnitId,ParentBusinessUnitId,DivisionName FROM PCRM_MSCRM.dbo.BusinessUnitBase AS curground inner join ShowSubDepartment PrevGroud on curground.ParentBusinessUnitId=PrevGroud.bid ) select * from ShowSubDepartment 查询某一机构下的 所有下级机构 参数980000 可选 SELECT d.DivisionName,st.bid,st.subid FROM BusinessUnitBase AS D CROSS APPLY fn_getsubtree(D.DivisionName) AS ST where DivisionName='990000' CROSS APPLY 每个机构调用辖下机构表值函数, 得到所有的机构辖下记录 ; WITH SetUnitlvl(bid, bname,subbid, lvl) AS ( -- Anchor Member (AM) SELECT BusinessUnitId,DivisionName,ParentBusinessUnitId, 1 FROM PCRM_MSCRM.dbo.BusinessUnitBase WHERE DivisionName='990000' UNION ALL -- Recursive Member (RM) SELECT BusinessUnitId, DivisionName,ParentBusinessUnitId ,PrevGroud.lvl+1 FROM PCRM_MSCRM.dbo.BusinessUnitBase AS curground inner join SetUnitlvl PrevGroud on curground.ParentBusinessUnitId=PrevGroud.bid ) select * from SetUnitlvl order by lvl 设置机构层级 --机构打平 select a.DivisionName as UnitCode, b.DivisionName as ParentUnitCode into #UnitUser from PCRM_MSCRM.dbo.BusinessUnit a left join PCRM_MSCRM.dbo.BusinessUnit b on b.BusinessUnitId = a.ParentBusinessUnitId and b.IsDisabled = 0 where a.IsDisabled = 0 select * from #UnitUser ; with tmp( ParentUnitCode, UnitCode,lvl,lel1,lel2,lel3,lel4,lel5,lel6,lel7,lel8,lel9) as( select ParentUnitCode, UnitCode ,1, UnitCode as lel1,UnitCode as lel2,UnitCode as lel3, UnitCode as lel4,UnitCode as lel5,UnitCode as lel6, UnitCode as lel7,UnitCode as lel8,UnitCode as lel9 from #UnitUser where ParentUnitCode is null union all select cur.ParentUnitCode, cur.UnitCode,prev.lvl+1, -- 规律对于lel2来说 除了第1层级机构的lel2 为它自己的CODE,其他都是以上一层级的 lel2 来赋值自己的lel2 对于lel3来说 除了第1,2层级机构的lel3 为它自己的CODE,其他都是以上一层级的 lel3来赋值自己的lel3 以此类推 prev.lel1 as lel1, case lvl when 1 then cur.UnitCode else prev.lel2 end as lel2, case lvl when 1 then cur.UnitCode when 2 then cur.UnitCode else prev.lel3 end as lel3, case lvl when 1 then cur.UnitCode when 2 then cur.UnitCode when 3 then cur.UnitCode else prev.lel4 end as lel4, case lvl when 1 then cur.UnitCode when 2 then cur.UnitCode when 3 then cur.UnitCode when 4 then cur.UnitCode else prev.lel5 end as lel5, case lvl when 1 then cur.UnitCode when 2 then cur.UnitCode when 3 then cur.UnitCode when 4 then cur.UnitCode when 5 then cur.UnitCode else prev.lel6 end as lel6, case lvl when 1 then cur.UnitCode when 2 then cur.UnitCode when 3 then cur.UnitCode when 4 then cur.UnitCode when 5 then cur.UnitCode when 6 then cur.UnitCode else prev.lel7 end as lel7, case lvl when 1 then cur.UnitCode when 2 then cur.UnitCode when 3 then cur.UnitCode when 4 then cur.UnitCode when 5 then cur.UnitCode when 6 then cur.UnitCode when 7 then cur.UnitCode else prev.lel8 end as lel8, case lvl when 1 then cur.UnitCode when 2 then cur.UnitCode when 3 then cur.UnitCode when 4 then cur.UnitCode when 5 then cur.UnitCode when 6 then cur.UnitCode when 7 then cur.UnitCode when 8 then cur.UnitCode else prev.lel9 end as lel9 from #UnitUser cur inner join tmp prev on prev.UnitCode=cur.ParentUnitCode ) select * from tmp Stuff 用法 从字符串A 的 第1个位置往后的0个长度 插入字符串B select STUFF('abcdefg',1,0,'1234') --结果为'1234abcdefg' select STUFF('abcdefg',1,1,'1234') --结果为'1234bcdefg' select STUFF('abcdefg',2,1,'1234') --结果为'a1234cdefg' select STUFF('abcdefg',2,2,'1234') --结果为'a1234defg' For xml path 将多行的结果合并成1行XML格式串,参数可以为空 或者XML 节点名 select stu_name,stu_course from stu_courses for xml path(''); --简单例子 PATH FOR XML if not object_id(N'Tempdb..#T') is null drop table #T Go Create table #T([款号] nvarchar(21),[规格] nvarchar(22)) Insert #T select N'A',N'毛巾' union all select N'A',N'坯布' union all select N'A',N'手巾' union all select N'b',N'手机' union all select N'b',N'电脑' Go --测试数据结束 SELECT [款号] , STUFF(( SELECT '/' + #T.[规格] FROM #T WHERE [款号] = a.[款号] FOR XML PATH('') ), 1, 1, '') AS [规格] FROM #T a GROUP BY a.[款号] 示例 with dic (productkeyname,productkey) as ( select case when CHARINDEX('网银', aa.Name)>0 then '网银' when CHARINDEX('及时语', aa.Name)>0 then '及时语' when CHARINDEX('三方存管', aa.Name)>0 then '三方存管' when CHARINDEX('银基通', aa.Name)>0 then '银基通' when CHARINDEX('外汇宝', aa.Name)>0 then '外汇宝' when CHARINDEX('黄金', aa.Name)>0 then '黄金' when CHARINDEX('保险', aa.Name)>0 then '保险' when CHARINDEX('周周赢', aa.Name)>0 then '周周赢' else '' end as Name, aa.ProductNumber from PCRM_MSCRM.dbo.ProductBase aa with(nolock) inner join pcrm_mscrm.dbo.spdb_category bb with(nolock) on bb.SPDB_categoryno = aa.ProductNumber where aa.ProductNumber like '04%' and (aa.Name like '%网银%' or aa.Name like '%及时语%' or aa.Name like '%三方存管%' or aa.Name like '%银基通%' or aa.Name like '%外汇宝%'or aa.Name like '%黄金%' or aa.Name like '%保险%' or aa.Name like '%周周赢%' ) and bb.SPDB_level = 6 ) select productkeyname,stuff((select ','+productkey from dic where productkeyname =a.productkeyname for xml path('')),1,1,'') from dic a group by productkeyname --取共有值和不共有值,都是唯一值 select Spdb_accountnumber from pcrm_mscrm.dbo.spdb_proddetail detail intersect select SPDB_accountnumber from PCRM_MSCRM.dbo.ContactBase select Spdb_accountnumber from pcrm_mscrm.dbo.spdb_proddetail detail except select SPDB_accountnumber from PCRM_MSCRM.dbo.ContactBase if object_id('tempdb..#tempcus') is not null Begin drop table #tempcus End EXEC sp_recompile procname 清除存储过程执行计划缓存 sp_create_plan_guide @name = N‘recompile_Guide’, @stmt = N‘SELECT * FROM Sales.SalesOrderHeader h, Sales.Customer c,Sales.SalesTerritory t WHERE h.CustomerID = c.CustomerID AND c.TerritoryID = t.TerritoryID AND CountryRegionCode = N”CA”;’, @type = N‘SQL’, @module_or_batch =NULL, @params =NULL, @hints = N‘OPTION (RECOMPILE)’ go exec sp_control_plan_guide N‘drop’,N‘recompile_Guide’ 上面的sp_create_plan_guide使用RECOMPILE参数,意思是说,每次碰到该语句,必须重新编译。sp_create_plan_guide运行后,该语句的执行计划缓存就被删除了,下次该语句再次执行就会重新编译。那么我为什么马上又删除这个plan guide呢?因为该语句的缓冲被清除后,我不希望该语句每次执行都重新编译,所以我删除了它,毕竟我执行sp_create_plan_guide的目的是删除该语句的执行计划缓存而已。所以如果你使用同样的手段,务必记得立即把sp_create_plan_guide建立的guide删除。 DBCC FREEPROCCACHE 清除缓存 GO DBCC DROPCLEANBUFFERS 清除缓存 GO exec sp_helpindex 查看索引 临时表在tempdb use tempdb exec sp_helpindex '#temptable' 统计信息 1、 在一个空表中有数据的改动。 2、 当统计信息创建时,表的行数只有500或以下,且后来统计对象中的引导列(统计信息的第一个字段数据)的更改次数大于500. 3、 当表的统计信息收集时,超过了500行,且统计对象的引导列(统计信息的第一个字段数据)后来更改次数超过500+表总行数的20%时 查看索引的统计信息更新时间 SELECT name AS index_name, STATS_DATE(OBJECT_ID, index_id) AS StatsUpdated FROM sys.indexes WHERE OBJECT_ID = OBJECT_ID('dbo.TEST1') GO 查看某表的所有统计信息列和名称 sp_helpstats 'Production.Product' ,'ALL' 查看统计信息基本信息 DBCC SHOW_STATISTICS(TEST1, PK_TEST1) (以下为08版本,SQL 2014更新了计算公式,使预估行数偏大) where xxxx=@aaa and cccc=@aaa 查询为参数时 ,无法准确预计,而取平均密度*表行数 xxxx 密度0.1 , cccc密度 0.2 0.1*0.2*1000=20 where xxxx=1 and cccc=2 查询为具体值时 ,密度取 当前值行数/总行数 预估计算公式不变 xxxx=1 有200行 cccc列有 100行 共1000行 200/1000 * 100/1000 *1000 =20 行 拼接字符串 IF isnull(@level,'')<>'' SET @sql=@sql + ' AND bs.spdb_level='''+ @level+'''' IF isnull(@Prjt_Name,'')<>'' SET @sql=@sql + ' AND main.Prjt_Name='''+ @Prjt_Name+'''' IF isnull(@Prjt_Stat_Cd,'')<>'' SET @sql=@sql + ' AND main.Prjt_Stat_Cd='''+ @Prjt_Stat_Cd+'''' declare @b datetime,@e datetime set @b =getdate() select * from dbo.contact set @e =getdate() select datediff(ms,@b,@e) SET Statistics IO OFF GO SET Statistics TIME OFF GO CREATE NonCLUSTERED INDEX [NCIX_tb_contact] ON [dbo].[contact] ( [NickName] ASC ) DROP INDEX index_name ON talbe_name ALTER TABLE table_name DROP INDEX index_name ALTER TABLE table_name DROP PRIMARY KEY --找客户表中持有产品的客户 select account_number,cust_name,accountclass from pcrm_report.dbo.tb_PCRM_ReportBase base with(nolock) where exists (select 1 from pcrm_mscrm.dbo.spdb_proddetail detail with(nolock) where detail.Spdb_accountnumber=base.account_number) select ROW_NUMBER() over(partition by base.account_number order by base.account_number) ,* from pcrm_report.dbo.tb_PCRM_ReportBase base with(nolock) inner join pcrm_mscrm.dbo.spdb_proddetail detail with(nolock) on base.account_number = detail.Spdb_accountnumber where detail.Spdb_productnumber like '01%' and detail.spdb_monthavgbal9 >0 统计一张表某字段多数种类的时候,应该一次统计出,不是各自统计然后UNION ALL 连接 此为错误的SQL select base.org_number, base.account_number, base.accountclass, '存款类' as productname, Sum(detail.Spdb_lastmonthbal) as productmonthbal, Sum(detail.spdb_monthavgbal9) as productmonthavg, 0 as IsHistory from pcrm_report.dbo.tb_PCRM_ReportBase base with(nolock) inner join pcrm_mscrm.dbo.spdb_proddetail detail with(nolock) on base.account_number = detail.Spdb_accountnumber where detail.Spdb_productnumber like '01%' and detail.spdb_monthavgbal9 >0 group by base.org_number, base.account_number, base.accountclass union all select base.org_number, base.account_number, base.accountclass, '贷款类' as productname, Sum(detail.Spdb_lastmonthbal) as productmonthbal, Sum(detail.spdb_monthavgbal9) as productmonthavg, 0 as IsHistory from pcrm_report.dbo.tb_PCRM_ReportBase base with(nolock) inner join pcrm_mscrm.dbo.spdb_proddetail detail with(nolock) on base.account_number = detail.Spdb_accountnumber where detail.Spdb_productnumber like '02%' and detail.spdb_monthavgbal9 >0 group by base.org_number, base.account_number, base.accountclass DETAIL 表的 CASE WHEN 部分 为正确的写法 select base.accountclass, base.org_number, Sum(detail.productcount), Sum(detail.productbal), Sum(detail.productavg) from (select case when Spdb_productnumber like '01%' then '存款类' when Spdb_productnumber like '02%' then '贷款类' when Spdb_productnumber like '0301%' then '结构性存款' when Spdb_productnumber like '0302%' then '专项理财产品' when Spdb_productnumber like '0304%' then '基金' when Spdb_productnumber like '0306%' then '三方存款' when Spdb_productnumber like '0303%' then '国债' when Spdb_productnumber like '0305%' then '证券集合理财' when Spdb_productnumber like '0310%' then '黄金' when Spdb_productnumber like '0307%' then '保险' end as spdb_productname, Spdb_accountnumber, COUNT(1) as productcount, Sum(spdb_lastmonthbal) as productbal, Sum(spdb_monthavgbal1) as productavg from pcrm_mscrm.dbo.spdb_proddetail detail with(nolock) group by case when Spdb_productnumber like '01%' then '存款类' when Spdb_productnumber like '02%' then '贷款类' when Spdb_productnumber like '0301%' then '结构性存款' when Spdb_productnumber like '0302%' then '专项理财产品' when Spdb_productnumber like '0304%' then '基金' when Spdb_productnumber like '0306%' then '三方存款' when Spdb_productnumber like '0303%' then '国债' when Spdb_productnumber like '0305%' then '证券集合理财' when Spdb_productnumber like '0310%' then '黄金' when Spdb_productnumber like '0307%' then '保险' end , Spdb_accountnumber) detail inner join pcrm_report.dbo.tb_PCRM_ReportBase base with(nolock) on base.account_number = detail.Spdb_accountnumber group by base.accountclass, base.org_number Union all 不是并行,每次都是独立执行,引起多次扫描 索引对GROUP BY 的影响 select fin_manager_no,accountclass,COUNT(1) from [Test].[dbo].[tb_ReportBase] group by fin_manager_no,accountclass 如建 fin_manager_no 单列索引,无法覆盖,扫描表 如建 fin_manager_no ,accountclass 多列索引 索引覆盖 非聚集索引扫描 CREATE NonCLUSTERED INDEX NIDX_fin_manager_no_accountclass ON [Test].[dbo].[tb_ReportBase] ( fin_manager_no ASC, accountclass ASC ) select fin_manager_no,accountclass,SUM(lastyearbal) from [Test].[dbo].[tb_ReportBase] group by fin_manager_no,accountclass 如SUM(lastyearbal) , lastyearbal 不在非聚集索引叶子节点,会扫描表 不会键查找,因为全量键查找不如表扫描 如要覆盖字段,索引建 CREATE NonCLUSTERED INDEX NIDX_fin_manager_no_accountclass ON [Test].[dbo].[tb_ReportBase] ( fin_manager_no ASC, accountclass ASC ) INCLUDE (lastyearbal) SQLServer中间接实现函数索引或者Hash索引 本文出处:http://www.cnblogs.com/wy123/p/6617700.html dbcc ind ( TESTDB3, [dbo.Suppliers], -1) DBCC PAGE (TESTDB3,1,109, 3);--也可以是DBCC PAGE (TESTDB3,1,2190, 1); --SQL MERGE 用法 create table SourceTable( id int , [DESC] varchar(50) ) create table TargetTable( id int , [DESC] varchar(50) ) delete TargetTable insert into TargetTable values (1,'存在更新') insert into TargetTable values (2,'存在更新') insert into TargetTable values (5,'不存在删除') insert into TargetTable values (6,'不存在删除') select * from SourceTable select * from TargetTable merge into TargetTable a --只对目标表DDL using SourceTable b on a.id=b.id when matched then --两表匹配 update set a.[DESC]=b.[DESC] when not matched then --原表有,目标表没有 insert values(b.id,b.[DESC]) when not matched by source then --目标表有, 原表没有 delete output $Action as [ACTION],inserted.id,inserted.[desc],deleted.id,deleted.[desc] ; -- SQL查锁 01.use master 02.go 03. 04.--检索死锁进程 05.select spid, blocked, loginame, last_batch, status, cmd, hostname, program_name 06.from sysprocesses 07.where spid in 08.( select blocked from sysprocesses where blocked <> 0 ) or (blocked <>0) KILL SPID 150 解锁