天天看点

ms sqlserver常用sql语句

获取SqlServer中表结构

SELECT syscolumns.name,systypes.name,syscolumns.isnullable,
syscolumns.length 
FROM syscolumns, systypes 
WHERE syscolumns.xusertype = systypes.xusertype 
AND syscolumns.id = object_id('你的表名')
 
-- 单独查询表递增字段
select [name] from syscolumns where 
id=object_id(N'你的表名') and COLUMNPROPERTY(id,name,'IsIdentity')=1

-- 获取表主外键约束
exec sp_helpconstraint   '你的表名'      

自定义函数递归调用

此方法适用于无限级分类情况下取出所有的父分类数据

CREATE function sp_GetAllParentByClassID
(  
   @classID int --参数
)
returns varchar(500)
as
begin
declare @ParentClassID varchar(15) --变量父ID
declare @result varchar(500)    --变量@result
set  @result = '' 
--首先根据传入的ClassID获取其父ID,ParentClassID
 SELECT    @ParentClassID = ParentClassID  FROM tClass 
    where  ClassID = @classID
if (@ParentClassID <> 0)--如果不是根节点
begin            
    -- 再将@ParentClassID父ID作为ClassID传入 进行自调用
     set @result =  dbo.sp_GetAllParentByClassID(@ParentClassID) + @ParentClassID+'_' 
    
end
    return  @result
end      

有的SQL版本运行上述SQL语句在dbo.sp_GetAllParentByClassID(@ParentClassID)会报错。

原因是,此时正的创建dbo.sp_GetAllParentByClassID函数,而还未创建,

在又在此处调用dbo.sp_GetAllParentByClassID(@ParentClassID),因此会提示没有这个对象,

解决办法是先去掉dbo.sp_GetAllParentByClassID(@ParentClassID)创建后再Alter修改 即可!

-- 如何将exec执行结果放入变量 num 中(自定义sql语句传出参数)

declare @num int,
@sqls nvarchar(4000)
set @sqls='select @a=count(*) from tableName '
exec sp_executesql @sqls,N'@a int output',@num output
select @num      

统计类

SELECT ZIP FROM Customers WHERE State = ''KY''  GROUP BY ALL ZIP
SELECT ZIP FROM Customers WHERE State = ''KY''  GROUP BY ZIP
SELECT ZIP, Count(ZIP) AS CustomersByZIP FROM Customers GROUP BY ZIP HAVING Count(ZIP) = 1
SELECT OrderID, Sum(Cost * Quantity) AS OrderTotal FROM Orders GROUP BY OrderID
SELECT Customer, OrderNumber, Sum(Cost * Quantity) AS OrderTotal FROM Orders GROUP BY Customer, OrderNumber WITH ROLLUP
SELECT Customer, OrderNumber, Sum(Cost * Quantity) AS OrderTotal FROM Orders GROUP BY Customer, OrderNumber WITH CUBE      

-----------------------------------

当CUBE的结果令人迷惑时(它经常是这样),可以添加一个GROUPING函数,如下所示:

SELECT GROUPING(Customer), OrderNumber, Sum(Cost * Quantity) AS OrderTotal FROM Orders GROUP BY Customer, OrderNumber WITH CUBE      
SELECT region, SUM(population), SUM(area)FROM bbc GROUP BY region HAVING SUM(area)>1000000      
Select     
  课程名,   
  [成绩>=85]=SUM(Case   When   成绩>=85   Then   1   Else   0   End)   ,   
  [85>成绩>70]=SUM(Case   When   成绩>=70   And   成绩<85   Then   1   Else   0   End)   ,  
  [成绩<60]=SUM(Case   When   成绩<60   Then   1   Else   0   End)   ,   
  总人数=Count(1)   
  from   TableName   
  Group   By   课程名   
  Order   By   课程名      

分组分段统计

select
    t.fromaccountid,
    onglogtimes=sum(case when t.logtimes1>0 then 1 else 0 end),
    twologtimes=sum(case when t.logtimes2=2 then 1 else 0 end),
    regnum     =sum(t.regStatus),
    t.regdate
from
(select
        a.fromaccountid,
        count(1) as logtimes1,                                                         --当日有登录记录的统计
        sum(case when datediff(mm,regdate,datetime)=0 then 1 else 0 end) as logtimes2,  --在注册当月登录的统计
        max(case when datediff(dd,regdate,datetime)=0 then 1 else 0 end) as regStatus,  --当日为注册操作的统计
        convert(char(10),a.regdate,120) as regdate
     from
         vgameuser a,loginlog b
     where
         a.accountid=b.playerid
     group by
         a.fromaccountid,convert(char(10),a.regdate,120))t
group by
    t.fromaccountid,t.regdate      

活跃时段统计

DECLARE @BeginDate7 DATETIME
  DECLARE @BeginDate365 DATETIME
  DECLARE @EndDate DATETIME
  SET @BeginDate7=dateadd(day,datediff(day,6,getdate()),0)
  SET @BeginDate365=DATEADD(MONTH,-6,GETDATE())
  SET @EndDate =GETDATE()
  

  --最近7日每日注册数
  SELECT COUNT(1) AS Nums,CONVERT(VARCHAR(10),RegTime,120) AS CountDate FROM dbo.T_User WHERE RegTime BETWEEN @BeginDate7 AND @EndDate
   GROUP BY CONVERT(VARCHAR(10),RegTime,120) 

  --最近1年每月注册数
  SELECT COUNT(1) AS Nums,CONVERT(VARCHAR(7),RegTime,120) AS CountDate FROM dbo.T_User WHERE RegTime BETWEEN @BeginDate365 AND @EndDate
   GROUP BY CONVERT(VARCHAR(7),RegTime,120) 

  --最近7日每日活跃数,按有登录算活跃
  SELECT COUNT(DISTINCT UserId) AS Nums,CONVERT(VARCHAR(10),InitTime,120) AS CountDate FROM dbo.T_UserLog WHERE InitTime BETWEEN @BeginDate7 AND @EndDate
   GROUP BY CONVERT(VARCHAR(10),InitTime,120) 
   
   --最近7日每日活跃时段 用with优化
  ; --这个分号一定要,除非这句是第一句
  WITH temp AS 
  ( 
  SELECT CONVERT(VARCHAR(13),InitTime,120) AS CountDate,COUNT(DISTINCT UserId) AS Nums FROM dbo.T_UserLog WHERE InitTime BETWEEN @BeginDate7 AND @EndDate
   GROUP BY CONVERT(VARCHAR(13),InitTime,120)
  )

  SELECT * FROM 
   temp a WHERE CountDate IN 
   (SELECT TOP 1 CountDate FROM temp b WHERE LEFT(CountDate,10)=LEFT(a.CountDate,10) ORDER BY Nums desc)
   
   
  --最近7日每日活跃时段 写法二 此sql待优化 每天只有一条记录,
   SELECT * FROM 
   (SELECT CONVERT(VARCHAR(13),InitTime,120) AS CountDate,COUNT(DISTINCT UserId) AS Nums FROM dbo.T_UserLog WHERE InitTime BETWEEN @BeginDate7 AND @EndDate
   GROUP BY CONVERT(VARCHAR(13),InitTime,120))a WHERE CountDate IN 
   (SELECT TOP 1 CountDate FROM (SELECT CONVERT(VARCHAR(13),InitTime,120) AS CountDate,COUNT(DISTINCT UserId) AS Nums FROM dbo.T_UserLog WHERE InitTime BETWEEN @BeginDate7 AND @EndDate
   GROUP BY CONVERT(VARCHAR(13),InitTime,120))b WHERE LEFT(CountDate,10)=LEFT(a.CountDate,10) ORDER BY Nums desc)
   

   
  --最近7日每日活跃时段 写法三 此sql待优化 此写法对于某天有多个时段活跃用户数相同时会有N条记录,而不是每天一条
  SELECT TOP 30 b.CountDate,b.Nums FROM (
SELECT CONVERT(VARCHAR(10),CountDate,120) AS CountDate,MAX(Nums) AS Nums FROM(
SELECT CONVERT(VARCHAR(13),InitTime,120) AS CountDate,COUNT(DISTINCT UserId) AS Nums FROM dbo.T_UserLog WHERE InitTime BETWEEN @BeginDate7 AND @EndDate
   GROUP BY CONVERT(VARCHAR(13),InitTime,120))a GROUP BY CONVERT(VARCHAR(10),CountDate,120))a INNER JOIN (
SELECT CONVERT(VARCHAR(13),InitTime,120) AS CountDate,COUNT(DISTINCT UserId) AS Nums FROM dbo.T_UserLog WHERE InitTime BETWEEN @BeginDate7 AND @EndDate
   GROUP BY CONVERT(VARCHAR(13),InitTime,120))b ON a.Nums=b.Nums AND a.CountDate=CONVERT(VARCHAR(10),b.CountDate,120)
   ORDER BY b.CountDate      

表数据去重

select * from T_Activity a inner join (
select name,address,max(id) as id from T_Activity group by name,address having count(1)>1)b on a.name=b.name and a.address=b.address where a.id<b.id

delete T_Activity from T_Activity a inner join (
select name,address,max(id) as id from T_Activity group by name,address having count(1)>1)b on a.name=b.name and a.address=b.address where a.id<b.id      

修改表结构,增加,修改,删除字段

sqlserver 修改表,修改表字段
-- 修改表名

EXEC sp_rename '原表名', '新表名';

-- 修改字段名

EXEC sp_rename '[表名].[字段名]','新字段名' ;


-- 添加字段

alter table 表名 add 列名 字段类型;

// 如果字段不为空,需要先添加一个默认值

alter table 表名 add 列名 字段类型 not null default 0


-- 修改字段类型

alter table 表名 alter column 字段名 字段类型;

 

-- 删除字段

alter table 表名 drop column 字段名;      

产生连续的时间表,如连续年,月,日等

-- 按年产生连续的
SELECT
 substring(CONVERT(NVARCHAR(10), DateAdd(YEAR, number, '2018-01-01'),120),1,4) AS GroupDay,type 
FROM
 master..spt_values 
WHERE type = 'p' AND number <= DateDiff(YEAR, '2018-01-01', getdate()) 
-- 按月产生连续的
SELECT
 substring(CONVERT(NVARCHAR(10), DateAdd(MONTH, number, '2019-01-01'),120),1,7) AS GroupDay,type 
FROM
 master..spt_values 
WHERE type = 'p' AND number <= DateDiff(MONTH, '2018-01-01', '2019-01-01') 
-- 按天产生连续的
SELECT
 CONVERT(NVARCHAR(10), DateAdd(day, number, '2019-01-01'),120) AS GroupDay,type 
FROM
 master..spt_values 
WHERE type = 'p' AND number <= DateDiff(day, '2019-01-01', getdate()) 
-- 按小时产生连续的
SELECT
 substring(convert(char(32),DATEADD(HH,number,CONCAT('2019-01-18',' ', '00:00')),120),1,16) AS GroupDay,type 
FROM
 master..spt_values 
WHERE type = 'p' AND DATEDIFF(HH,DATEADD(HH,number,CONCAT('2019-01-18',' ', '00:00')),CONCAT('2019-01-18',' ', '23:00'))>=0      

查询库,表信息

---1.查询数据库中的所有数据库名:
SELECT Name FROM Master..SysDatabases ORDER BY Name  

---2.查询某个数据库中所有的表名:
SELECT Name FROM SysObjects Where XType='U' ORDER BY Name

--3.查询表结构信息,表说明,字段信息
SELECT 表名称= d.name,
       表说明= isnull(f.value,''),
       排序号= a.colorder,
       列名称= a.name,
       列说明= isnull(g.[value],''),
       标识列= case when COLUMNPROPERTY( a.id,a.name,'IsIdentity')=1 then 1 else 0 end,
       主键列= case when exists(SELECT 1 FROM sysobjects where xtype='PK' and parent_obj=a.id and name in (SELECT name FROM sysindexes WHERE indid in( SELECT indid FROM sysindexkeys WHERE id = a.id AND colid=a.colid))) then 1 else 0 end,
       列类型= b.name,
       字节数= a.length,
       列长度= COLUMNPROPERTY(a.id,a.name,'PRECISION'),
       小数位= isnull(COLUMNPROPERTY(a.id,a.name,'Scale'),0),
       允许空= case when a.isnullable=1 then 1 else 0 end,
       默认值= isnull(e.text,'')
FROM  syscolumns a
LEFT JOIN  systypes b on a.xusertype=b.xusertype
INNER JOIN sysobjects d on  a.id=d.id  and d.xtype='U' and  d.name<>'dtproperties'
LEFT JOIN  syscomments e on  a.cdefault=e.id
LEFT JOIN  sys.extended_properties g on  a.id=G.major_id and a.colid=g.minor_id  
LEFT JOIN  sys.extended_properties f on  d.id=f.major_id and f.minor_id=0
--where d.name='表名'
ORDER BY 表名称 ASC,排序号 ASC

--4.查询表的行记录数,按大小排序
SELECT a.name,b.rows
FROM sysobjects AS a INNER JOIN 
sysindexes AS b ON a.id = b.id 
WHERE (a.type = 'u') AND (b.indid IN (0, 1)) 
ORDER BY b.rows DESC