行列互转



create  table  test(id  int ,name  varchar ( 20 ),quarter  int ,profile  int ) 
insert  into  test  values ( 1 , ' a ' , 1 , 1000 )
insert  into  test  values ( 1 , ' a ' , 2 , 2000 )
insert  into  test  values ( 1 , ' a ' , 3 , 4000 )
insert  into  test  values ( 1 , ' a ' , 4 , 5000 )
insert  into  test  values ( 2 , ' b ' , 1 , 3000 )
insert  into  test  values ( 2 , ' b ' , 2 , 3500 )
insert  into  test  values ( 2 , ' b ' , 3 , 4200 )
insert  into  test  values ( 2 , ' b ' , 4 , 5500 )
select  *  from  test

-- 行转列
select  id,name,
[ 1 ]  as  "一季度",
[ 2 ]  as  "二季度",
[ 3 ]  as  "三季度",
[ 4 ]  as  "四季度",
[ 5 ]  as  " 5 "
from
test
pivot
(
sum (profile)
for  quarter  in
( [ 1 ] , [ 2 ] , [ 3 ] , [ 4 ] , [ 5 ] )
)
as  pvt


create  table  test2(id  int ,name  varchar ( 20 ), Q1  int , Q2  int , Q3  int , Q4  int )
insert  into  test2  values ( 1 , ' a ' , 1000 , 2000 , 4000 , 5000 )
insert  into  test2  values ( 2 , ' b ' , 3000 , 3500 , 4200 , 5500 )
select  *  from  test2

-- 列转行
select  id,name,quarter,profile
from
test2
unpivot
(
profile
for  quarter  in
( [ Q1 ] , [ Q2 ] , [ Q3 ] , [ Q4 ] )

as  unpvt




sql替换字符串 substring replace



-- 例子1:
update  tbPersonalInfo  set  TrueName  =  replace (TrueName, substring (TrueName, 2 , 4 ), ' ** ' )  where  ID  =  1

-- 例子2:
update  tbPersonalInfo  set  Mobile  =  replace (Mobile, substring (Mobile, 4 , 11 ), ' ******** ' )  where  ID  =  1

-- 例子3:
update  tbPersonalInfo  set  Email  =  replace (Email, ' chinamobile ' , ' ****** ' )  where  ID  =  1



 



SQL查询一个表内相同纪录 having



如果一个ID可以区分的话,可以这么写

select  *  from  表  where  ID  in  (
select  ID  from  表  group  by  ID  having  sum ( 1 ) > 1 )

如果几个 ID才能区分的话,可以这么写


select  *  from  表  where  ID1 + ID2 + ID3  in
( select  ID1 + ID2 + ID3  from  表  group  by  ID1,ID2,ID3  having  sum ( 1 ) > 1 )

其他回答:数据表是zy_bho,想找出ZYH字段名相同的记录


-- 方法1:    
SELECT    * FROM   zy_bho  a   WHERE    EXISTS  
  ( SELECT    1    FROM   zy_bho   WHERE    [ PK ]    <>   a. [ PK ]    AND   ZYH   =   a.ZYH) 
   
-- 方法2:
select   a. *    from   zy_bho  a   join   zy_bho  b 
       on   (a. [ pk ] <> b. [ pk ]    and   a.zyh = b.zyh) 
   
-- 方法3:
select    *    from   zy_bbo   where   zyh   in  
( select   zyh   from   zy_bbo   group    by   zyh   having    count (zyh) > 1 ) 
-- 其中pk是主键或是 unique的字段。 





把多行SQL数据变成一条多列数据,即新增列



Select
DeptName = O.OUName,
' 9G ' = Sum ( Case  When  PersonalGrade = 9  Then  1  Else  0  End ),
' 8G ' = Sum ( Case  When  PersonalGrade = 8  Then  1  Else  0  End ),
' 7G4 ' = Sum ( Case  When  PersonalGrade = 7  AND  JobGrade  = 4  Then  1  Else  0  End ),
' 7G3 ' = Sum ( Case  When  PersonalGrade = 7  AND  JobGrade  = 3  Then  1  Else  0  End ),
' 6G ' = Sum ( Case  When  PersonalGrade = 6  Then  1  Else  0  End ),
' 5G3 ' = Sum ( Case  When  PersonalGrade = 5  AND  JobGrade  = 3  Then  1  Else  0  End ),
' 5G2 ' = Sum ( Case  When  PersonalGrade = 5  AND  JobGrade  = 2  Then  1  Else  0  End ),
' 4G ' = Sum ( Case  When  PersonalGrade = 4  Then  1  Else  0  End ),
' 3G2 ' = Sum ( Case  When  PersonalGrade = 3  AND  JobGrade  = 2  Then  1  Else  0  End ),
' 3G1 ' = Sum ( Case  When  PersonalGrade = 3  AND  JobGrade  = 1  Then  1  Else  0  End ),
' 2G ' = Sum ( Case  When  PersonalGrade = 2  Then  1  Else  0  End ),
' 1G ' = Sum ( Case  When  PersonalGrade = 1  Then  1  Else  0  End ),
-- ' 未定级'=Sum(Case When PersonalGrade=NULL Then 1 Else 0 End) 



 

表复制



insert  into  PhoneChange_Num ( [ IMSI ] ,Num)
SELECT  [ IMSI ]
      , count ( [ IMEI ] )  as  num
   FROM  [ Test ] . [ dbo ] . [ PhoneChange ]  group  by  [ IMSI ]  order  by  num  desc



语法1:Insert INTO table(field1,field2,...) values(value1,value2,...)

语法2:Insert into Table2(field1,field2,...) select value1,value2,... from Table1(要求目标表Table2必须存在,由于目标表Table2已经存在,所以我们除了插入源表Table1的字段外,还可以插入常量。)

语法3:SELECT vale1, value2 into Table2 from Table1(要求目标表Table2不存在,因为在插入时会自动创建表Table2,并将Table1中指定字段数据复制到Table2中。)

语法4:使用导入导出功能进行全表复制。如果是使用【编写查询以指定要传输的数据】,那么在大数据表的复制就会有问题?因为复制到一定程度就不再动 了,内存爆了?它也没有写入到表中。而使用上面3种语法直接执行是会马上刷新到数据库表中的,你刷新一下mdf文件就知道了。

 

利用带关联子查询Update语句更新数据



-- 方法1:
Update  Table1  set  c  =  ( select  c  from  Table2  where  a  =  Table1.a)  where  c  is  null  

-- 方法2:
update   A
set   newqiantity = B.qiantity
from   A,B
where   A.bnum = B.bnum 

-- 方法3:
update
    ( select  A.bnum ,A.newqiantity,B.qiantity  from  A  left  join  B  on  A.bnum = B.bnum)  AS  C
set  C.newqiantity  =  C.qiantity
where  C.bnum  = XX 




连接远程服务器



-- 方法1:
select  *    from  openrowset ( ' SQLOLEDB ' , ' server=192.168.0.67;uid=sa;pwd=password ' , ' SELECT * FROM BCM2.dbo.tbAppl ' )

-- 方法2:
select  *    from  openrowset ( ' SQLOLEDB ' , ' 192.168.0.67 ' ; ' sa ' ; ' password ' , ' SELECT * FROM BCM2.dbo.tbAppl ' )  



 


Date 和 Time 样式



 


不带世纪数位 (yy) (1)

带世纪数位 (yyyy)

标准

输入/输出 (3)

-

0100 (1,2)

默 认

mon dd yyyy hh:miAM(或 PM)

1

101

美 国

mm/dd/yyyy

2

102

ANSI

yy.mm.dd

3

103

英 国/法国

dd/mm/yyyy

4

104

德 国

dd.mm.yy

5

105

意 大利

dd-mm-yy

6

106(1)

-

dd mon yy

7

107(1)

-

mon dd, yy

8

108

-

hh:mi:ss

-

9109 (1,2)

默 认设置 + 毫秒

mon dd yyyy hh:mi:ss:mmmAM(或 PM)

10

110

美 国

mm-dd-yy

11

111

日 本

yy/mm/dd

12

112

ISO

yymmdd

yyyymmdd

-

13113 (1,2)

欧 洲默认设置 + 毫秒

dd mon yyyy hh:mi:ss:mmm(24h)

14

114

-

hh:mi:ss:mmm(24h)

-

20120 (2)

ODBC 规范

yyyy-mm-dd hh:mi:ss(24h)

-

21121 (2)

ODBC 规范(带毫秒)

yyyy-mm-dd hh:mi:ss.mmm(24h)

-

126 (4)

ISO8601

yyyy- mm-ddThh:mi:ss.mmm(无空格)

-

127(6, 7)

带时区 Z 的 ISO8601。

yyyy-mm-ddThh:mi:ss.mmmZ

(无 空格)

-

130 (1,2)

回历 (5)

dd mon yyyy hh:mi:ss:mmmAM

-

131 (2)

回历 (5)

dd/mm/yy hh:mi:ss:mmmAM

 


-- 语句及查询结果:
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  0 ):  05  16  2006  10 :57AM
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  1 ):  05 / 16 / 06
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  2 ):  06.05 . 16
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  3 ):  16 / 05 / 06
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  4 ):  16.05 . 06
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  5 ):  16 - 05 - 06
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  6 ):  16  05  06
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  7 ):  05  16 ,  06
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  8 ):  10 : 57 : 46
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  9 ):  05  16  2006  10 : 57 : 46 :827AM
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  10 ):  05 - 16 - 06
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  11 ):  06 / 05 / 16
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  12 ):  060516
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  13 ):  16  05  2006  10 : 57 : 46 : 937
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  14 ):  10 : 57 : 46 : 967
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  20 ):  2006 - 05 - 16  10 : 57 : 47
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  21 ):  2006 - 05 - 16  10 : 57 : 47.157
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  22 ):  05 / 16 / 06  10 : 57 : 47  AM
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  23 ):  2006 - 05 - 16
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  24 ):  10 : 57 : 47
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  25 ):  2006 - 05 - 16  10 : 57 : 47.250
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  100 ):  05  16  2006  10 :57AM
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  101 ):  05 / 16 / 2006
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  102 ):  2006.05 . 16
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  103 ):  16 / 05 / 2006
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  104 ):  16.05 . 2006
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  105 ):  16 - 05 - 2006
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  106 ):  16  05  2006
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  107 ):  05  16 ,  2006
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  108 ):  10 : 57 : 49
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  109 ):  05  16  2006  10 : 57 : 49 :437AM
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  110 ):  05 - 16 - 2006
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  111 ):  2006 / 05 / 16
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  112 ):  20060516
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  113 ):  16  05  2006  10 : 57 : 49 : 513
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  114 ):  10 : 57 : 49 : 547
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  120 ):  2006 - 05 - 16  10 : 57 : 49
SELECT  CONVERT ( varchar ( 100 ),  GETDATE (),  121 ):  2006



对上面进行动态生成字符串:



declare  @sql1  nvarchar ( 200 ), @sql2  nvarchar ( 200 )
declare  @count  nvarchar ( 100 );
set  @sql1  =  ' SELECT CONVERT(varchar(100), GETDATE(), 0) '
set  @sql2  =  ' SELECT @count = CONVERT(varchar(100), GETDATE(), 0) '
exec  sp_executesql   @sql2 ,N ' @count nvarchar(50) out ' , @count  out
print  @sql1  + ' : ' +  @count






-- SQL Server 仅保证往返转换(即从原始数据类型进行转换后又返回原始数据类型的转换)在各版本间产生相 同值。
DECLARE  @myval  decimal  ( 5 ,  2 )
SET  @myval  =  193.57
SELECT  CAST ( CAST ( @myval  AS  varbinary ( 20 ))  AS  decimal ( 10 , 5 ))
--  Or, using CONVERT
SELECT  CONVERT ( decimal ( 10 , 5 ),  CONVERT ( varbinary ( 20 ),  @myval ))
-- 输出193.57000
-- 输 出193.57000






-- bigint数据类型的字段截取(其它类型也一样)
select  substring ( CONVERT ( varchar ( 15 ),字段 名), 11 , 9 )  from  表名
select  substring ( cast (字段名  as  varchar ( 50 ), 6 , 9 ))  from  表名



 

 SQL中的相除



-- SQL中的相除
SELECT  CASE  WHEN  ISNULL (A + B, 0 ) <> 0  THEN  
LTRIM ( CONVERT ( DEC ( 18 , 2 ),A * 100.0 / (A + B))) + ' % '    ELSE  ''  END  AS  ' 百分数 '  
FROM  TB 



 



-- 百分比的不同格式
select  
LTRIM ( CONVERT ( DEC ( 18 , 2 ), 42 * 100.0 / 96 )) + ' % '  AS  ' 百分数string '  , -- DEC=decimal
CONVERT ( decimal ( 10 , 2 ), 42 * 100.0 / 96 )  AS  ' 百分数dec ' ,  -- 100 与 100.0是不一样的
CONVERT ( decimal ( 10 , 2 ), 42 * 100 / 96 )  AS  ' 没有保留到小数点 '
-- from Tb
order  by  百分数dec  desc
-- 43.75%    43.75    43.00
 
-- 方法二:
Select  ( Convert ( varchar ( 50 ), Round ( 42 * 100.0 / 96 , 3 )) + ' % ' )  as  百分比  -- from A
-- 43.750000%




四舍五入



/* ROUND ( numeric_expression , length [ ,function ] )
function 必 须为 tinyint、smallint  或 int。
如果省略 function 或其值为 0(默认值),则将舍 入 numeric_expression。
如果指定了0以外的值,则将截断 numeric_expression。 */
SELECT  ROUND ( 150.45648 ,  2 ); -- 保留小数点后两位,需要四舍五入
SELECT  ROUND ( 150.45648 ,  2 ,  0 ); -- 保留小数点后两位,0为默认值,表示进行四舍五入
SELECT  ROUND ( 150.45648 ,  2 ,  1 ); -- 保留小数点后两位,不需要四舍五入, 这里除0以外都是有同样的效果
SELECT  ROUND ( 150.45648 ,  2 ,  2 ); -- 保留小数点后两位,不需要四舍五入,这里除0以外都是有同样的效果
-- 150.46000
-- 150.45000
-- 150.45000
-- 150.45000



 

对字段出现NULL值的处理



-- 判断某些字段是否为空
-- case
select  case  when  ' 字段名 '  is  null  then  ' \N '  else  convert ( varchar ( 20 ), ' 字段名 ' )  end  as  ' NewName '
select  case  when  null  is  null  then  ' \N '  else  convert ( varchar ( 20 ), null )  end  as  ' NewName '

-- SQL Server 2005:coalesce
select  coalesce ( ' 字符串类型字段 ' , ' \N ' )  as  ' NewName '
select  coalesce ( convert ( varchar ( 20 ), ' 非字符串类型字段 ' ), ' \N ' )  as  ' NewName '
select  coalesce ( convert ( varchar ( 20 ), null ), ' \N ' )  as  ' NewName '

-- coalesce,返回其 参数中的第一个非空表达式
select  Coalesce ( null , null , 1 , 2 , null ) union
select  Coalesce ( null , 11 , 12 , 13 , null ) union
select  Coalesce ( 111 , 112 , 113 , 114 , null )



 

count 的几种情况



-- 第一种
select  count ( * )  from  tablename

-- 第二种
select  count (ID)  from  tablename

-- 第三种,1换成其它值也是可以的
select  count ( 1 )  from  tablename

/*
--第四种,这个不存在性能问题
idint 表ID(如果 indid = 0 或255)。否则为索引所属表 的ID
Indid smallint 索引ID:
0=表
1=聚簇索引
>1=非聚簇索引
255=具有 text或image数据的表条目。
rows int 基于indid=0 和 indid=1地数据级行数,该值对于indid>1重 复。如果indid=255,rows设置为0。
当表没有聚簇索引时,Indid = 0 否则为 1。 
*/
select  rows,indid  from  sysindexes  where  id  =  object_id ( ' tablename ' )  and  indid  in  ( 0 , 1 ) 




Union all

 



-- 把两个相同结构的表union后插入到一个新表中
select  *  
into  table_now
from  table_1
union  all  select  *  from  table_2
-- Truncate table table_now



 

查 看数据库缓存的SQL



-- 适用MSSQL2000、MSSQL2005
use  master
declare  @dbid  int
Select  @dbid  =  dbid  from  sysdatabases  where  name  =  ' Test ' -- 修改成数据库的名称
select
dbid,UseCounts ,RefCounts,CacheObjtype,ObjType,
DB_Name (dbid)  as  DatabaseName,SQL
from  syscacheobjects
where  dbid = @dbid
order  by  dbid,useCounts  desc ,objtype




删除计划缓存



-- 删除整个数据库的计划缓存
DBCC  FREEPROCCACHE

-- 删除某个数据库的计划缓存
USE  master
DECLARE  @dbid  INT
SELECT  @dbid = dbid  FROM  sysdatabases  WHERE  NAME  =  ' 表名 '
DBCC  FLUSHPROCINDB ( @dbid )




导出时加入特殊字符

情况一:全部字段都需要加字符,在这里设置【文本限定符】就可以了。

postgrepsql查询2个列相除_数据库


情况二:



-- 某些特殊的字段需要加单引号(或者其它符号) 
SELECT
       [ ID ]
      , '''' + convert ( varchar ( 25 ), [ ts ] , 121 ) + ''''  as  [ ts ]
      , '''' + convert ( varchar ( 25 ), [ otherParty ] , 121 ) + ''''  as  [ otherParty ]
      , '''' + convert ( varchar ( 25 ), [ StartTime ] , 121 ) + ''''  as  [ StartTime ]
      , [ CcCause ]
      , [ RrCause ]
   FROM  [ 表 ]



效果:74983006,'2010-03-09 23:59:10.000'

 

TRUNCATE TABLE [Table Name]

下面是对Truncate语句在MSSQLServer2000中用法和原理的说明:

Truncate是SQL中的一个删除数据表内容的语句,用法是:

Truncate table 表名 速度快,而且效率高,因为:
TRUNCATE TABLE 在功能上与不带 WHERE 子句的 DELETE 语句相同:二者均删除表中的全部行。但 TRUNCATE TABLE 比 DELETE 速度快,且使用的系统和事务日志资源少。
DELETE 语句每次删除一行,并在事务日志中为所删除的每行记录一项。TRUNCATE TABLE 通过释放存储表数据所用的数据页来删除数据,并且只在事务日志中记录页的释放。
TRUNCATE TABLE 删除表中的所有行,但表结构及其列、约束、索引等保持不变。新行标识所用的计数值重置为该列的种子。如果想保留标识计数值,请改用 DELETE。如果要删除表定义及其数据,请使用 DROP TABLE 语句。
对于由 FOREIGN KEY 约束引用的表,不能使用 TRUNCATE TABLE,而应使用不带 WHERE 子句的 DELETE 语句。由于 TRUNCATE TABLE 不记录在日志中,所以它不能激活触发器。
TRUNCATE TABLE 不能用于参与了索引视图的表。 

 

其它



-- 查看内存状态
dbcc  memorystatus

-- 查看哪个引起的阻塞,blk 
EXEC  sp_who active 

-- 查看锁住了那个资源id,objid
EXEC  sp_lock 

-- 当前查询 分析器SPID
-- 查询分析器的状态栏中可以看到
-- 比如sa(57),这就表示当前查询分析器SPID为57,这样在使用profile的时候就可以指定当前窗体进行监控



 

参考文献

数据库表行转列,列转行终极方案

行列互转(动态脚本)

SELECT INTO 和 INSERT INTO SELECT 两种表复制语句

非常有用的sql脚本 

SQL中OpenDataSource与OpenRowSet的应用

SQL中CONVERT转化函数的用法

CAST 和 CONVERT (Transact-SQL) 

精度、小数位数和长度 (Transact-SQL) 

ROUND (Transact-SQL)