原文:SQL点滴21—几个有点偏的语句

SQL语句是一种集合操作,就是批量操作,它的速度要比其他的语言快,所以在设计的时候很多的逻辑都会放在sql语句或者存储过程中来实现,这个是一种设计思想。但是今天我们来讨论另外一个话题。Sql页提供了丰富的函数供我们使用,还有很多操作有意想不到的结果,今天这个随笔来看看一些不常见到的sql语句。这些语句不像普通的增删查那样平白,它的奇妙之处有时候让人另眼相看。

  

1.  假设我想把Person.Contact表中所有人的名字用逗号连接起来,串成一个字符串,可能会想到使用游标把FirstName查出来然后逐行赋值给一个字符串变量,可是使用游标的代价是很大的。看看下面的代码:

declare @names varchar(1000)=''—注意赋值为空字符串是必须的
select @names=isnull(@names,'')+FirstName+',' from Person.Contact
print @names

查询得到的结果是(用的是AdventureWorks数据库中的Contact表):Gustavo,Catherine,Kim,Humberto,Pilar,Frances,Margaret,Carla,Jay,Ronald,Samuel,James,Robert,Fran?ois,Kim,Lili,Amy,Anna,Milton,Paul,Gregory,J. Phillip,Michelle,Sean,Phyllis,Marvin,Michael,Cecil,Oscar,Sandra,Selena,Emilio,Maxwell,Mae,Ramona,Sabria,Hannah,Kyley,Tom,Thomas,John,Chris,

使用其他的语句是不能达到这个效果的,不过我没有深入考虑过,但是这个是很简单的语句。

还有一个地方和这个类似,就是在行列转换的时候拼接动态sql语句,首先使用下面的语句创建一个临时表:

create table #DepartCost
(
id int,
Department varchar(20),
Material varchar(20),
Number int
)
insert into #DepartCost values
(1,'厂房1','材料1',1),
(1,'厂房2','材料2',2),
(1,'厂房1','材料3',1),
(1,'厂房3','材料3',1),
(1,'厂房2','材料3',1),
(1,'厂房3','材料1',1),
(1,'厂房1','材料1',2),
(1,'厂房1','材料2',1),
(1,'厂房1','材料3',1)

表中的数据如下:

图1

我们看到每个厂房分别使用的材料数量,还是一个老问题,如果我们想知道针对每种材料,每个厂房耗费的材料数量是多少该怎么写呢。有一种笨的方法,如下:

select Department,
sum(case Material when '材料1' then Number else 0 end) as [材料1],
sum(case Material when '材料2' then Number else 0 end) as [材料2],
sum(case Material when '材料3' then Number else 0 end) as [材料3]
from #DepartCost
group by Department

查询结果如下:

图2

说这种方法笨是因为需要事先知道材料的类别,如果有很多种材料这个语句就会很长了,下面我们使用动态语句来实现这个功能:

declare @sql varchar(1000)
set @sql = 'select Department '
select @sql = @sql+', sum(case Material when '''+Material+''' then Number else 0 end) as ['+Material+']' from
(select distinct Material from #DepartCost) as a
select @sql = @sql + ' from #DepartCost group by Department '
exec(@sql)

我们来看看@sql字符串变量到底长得什么样子,使用print @sql将它打印出来:

select Department , sum(case Material when '材料' then Number else 0 end) as [材料], sum(case Material when '材料' then Number else 0 end) as [材料], sum(case Material when '材料' then Number else 0 end) as [材料] from #DepartCost group by Department

这个语句和上面那个是一样的,当然exec(@sql)得到的结果也是一样的了。这里我不知道这种特性有个什么说法,不像子查询,也不是case语句。

  

2.写一个语句获得当前这个月有多少天

这个涉及到日期和时间,初步的思路是查询得到本月的最后一天,然后用datepart获得天数,这是一个很直接的方法。来看下面的语句:

select 
datepart(
dd,--datepart的参数取本月最后一天的天数,即为本月的天数
dateadd(dd,--取下个月的第一天的前一天,就是本月最后一天
-1,
dateadd(mm,--取下一个月的第一天
1,
cast(cast(year(getdate())as varchar)+'-'+ --取当前的年
cast(month(getdate()) as varchar)+'-01'--取这个月的第一天
as datetime))) --转换成时间
)

这个语句没有什么悬念,仅仅是时间函数的使用,只要知道这个思路就很容易写出来。

  

3.假设我们有一张销售表,现在要查出销售单价,但是我们想不适用具体的价钱来显示,而是显示为一个范围,比如价钱是1-100元要显示“1 to 100”,100-200要显示“100 to 200”,等等。来看代码:

select so.UnitPrice, NewUnitPrice =  
case when so.UnitPrice is null then 'unknown' --NewPrice一点类似于C#里面的var变量,事先不定义类型,从赋值结果里面确认它的类型
when so.UnitPrice between 100 and 200 then '100 to 200'
when so.UnitPrice between 201 and 300 then '200 to 300'
when so.UnitPrice between 301 and 400 then '300 to 400'
else cast(so.UnitPrice as varchar(10)) --这里一定要转换成字符串
end
from Sales.SalesOrderDetail so order by UnitPrice

要注意的是最后剩下一些不做归类转换的必须将类型转换为varchar,否则会有语法错误。结果如下:

图3

  

4.假设有一张联系人姓名表,现在想查出这个表中姓相同的联系人的数目,猛一看有点懵,其实很简单,来看代码:

select c.LastName,num_LastName=COUNT(1) from Person.Contact c group by c.LastName

图4

注意要统计那个字段就要对那个字段进行聚合操作,如图我们可以看到有77个姓Davis的,71个姓Lin的,90个姓Waston的等等。

  

5.查找数据库中所有表的行数

select ROW_NUMBER() over(order by TABLE_NAME) as rownumber,TABLE_SCHEMA, TABLE_NAME into #table from INFORMATION_SCHEMA.TABLES where TABLE_TYPE='BASE TABLE'
declare @count int
select @count = COUNT(*) from #table
declare @index int = 1
declare @tablename nvarchar(200)
declare @sql nvarchar(1000)
while @index<@count
begin
select @tablename=TABLE_SCHEMA+'.'+TABLE_NAME from #table where rownumber=@index
select @sql= 'select '''+@tablename+''' as tablename, COUNT(*) as rowscount from '+ @tablename
exec (@sql)
if @index>@count
break
set @index = @index+1
end
drop table #table

这个方法很一般,求教高手们提供一个更加灵活的方法。

SQL点滴21—几个有点偏的语句的更多相关文章

  1. sql点滴40—mysql乱码问题总结

    原文:sql点滴40-mysql乱码问题总结 本文将为大家讲解如何处理Java连接过程中的MySQL中文乱码问题.一般MySQL中文乱码问题都是与字符集有关,这里作者的经历也大致差不多. MySQL默 ...

  2. SQL点滴19—T-SQL中的透视和逆透视

    原文:SQL点滴19-T-SQL中的透视和逆透视 透视 今天抽一点时间来看看透视和逆透视语句,简单的说就是行列转换.假设一个销售表中存放着产品号,产品折扣,产品价格三个列,每一种产品号可能有多种折扣, ...

  3. Azure SQL Database (21) 将整张表都迁移到Azure Stretch Database里

    <Windows Azure Platform 系列文章目录>  Azure SQL Database (19) Stretch Database 概览      Azure SQL Da ...

  4. sql点滴42—mysql中的时间转换

    原文:sql点滴42-mysql中的时间转换 UNIX时间戳转换为日期用函数: FROM_UNIXTIME() select FROM_UNIXTIME(1156219870); 日期转换为UNIX时 ...

  5. sql点滴41—MyISAM 和 InnoDB 讲解

    原文:sql点滴41-MyISAM 和 InnoDB 讲解 InnoDB和MyISAM是许多人在使用MySQL时最常用的两个表类型,这两个表类型各有优劣,视具体应用而定.基本的差别为:MyISAM类型 ...

  6. sql点滴42—mysql中的数据结构

    原文:sql点滴42-mysql中的数据结构 MySQL 的数值数据类型可以大致划分为两个类别,一个是整数,另一个是浮点数或小数.许多不同的子类型对这些类别中的每一个都是可用的,每个子类型支持不同大小 ...

  7. sql点滴41—mysql常见sql语法

    原文:sql点滴41-mysql常见sql语法 ALTER TABLE:添加,修改,删除表的列,约束等表的定义. 查看列:desc 表名; 修改表名:alter table t_book rename ...

  8. sql点滴38—SQL Server 2008和SQL Server 2008 R2导出数据的选项略有不同

    原文:sql点滴38—SQL Server 2008和SQL Server 2008 R2导出数据的选项略有不同 说明: 以前要将一个表中的数据导出为脚本,只有用存储过程.现在在SQL Server ...

  9. sql点滴37—mysql中的错误Data too long for column '' at row 1

    原文:sql点滴37-mysql中的错误Data too long for column '' at row 1   1.MYSQL服务 我的电脑——(右键)管理——服务与应用程序——服务——MYSQ ...

随机推荐

  1. LVM 命令集总结(转)

    PV 命令 下面的命令是在与物理卷相关的操作中最常用的命令: lsdev 列出ODM中的设备. chdev 修改设备的特征. mkdev 增加一个设备到系统中. chpv 修改物理卷的状态. lspv ...

  2. nginx 提供静态内容

    Serving Static Content 提供静态内容 原文地址:http://nginx.com/resources/admin-guide/serving-static-content/ Th ...

  3. C#程序(含多个Dll)合并成一个Exe

    把C#程序(含多个Dll)合并成一个Exe的超简单方法   开发程序的时候经常会引用一些第三方的DLL,然后编译生成的exe文件就不能脱离这些DLL独立运行了. 但是,很多时候我们本想开发一款只需要一 ...

  4. Python网络02 Python服务器进化

    原文:Python网络02 Python服务器进化 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! **注意,在Python 3. ...

  5. Xenomai 3 和 PREEMPT_RT 有哪些优势相比,

    Q: 我可以在我的开发板PREEMPT_RT直接在内核环境中执行POSIX应用, 使用Xenomai3 这是什么原因它? A:假设你的应用程序已经完全是POSIX,而且性能也满足,则,而且也没有理由去 ...

  6. spring交易声明的几个传播特性

    近期遇到了一个spring事务导致的问题,所以写了几个小程序了解了一下事务的传播特性,以下分别举样例分别看看事务的传播特性. 事务的几种传播特性 1. PROPAGATION_REQUIRED: 假设 ...

  7. NSIS API 函数常用备份

    原文:NSIS API 函数常用备份 关闭程序: System::Call `user32::AnimateWindow(i$HWNDPARENT,i200,i${AW_BLEND}|${AW_HID ...

  8. 实现键值对存储(三):Kyoto Cabinet 和LevelDB的架构比較分析

    译自  Emmanuel Goossaert (CodeCapsule.com) 在本文中,我将会逐组件地把Kyoto Cabinet 和 LevelDB的架构过一遍.目标和本系列第二部分讲的差点儿相 ...

  9. krpano漫游加方向性3D声音(这篇文章已被移到krpano中国网站 krpano360.com)

    需求:      在场景转换视角时.会出现不同方位的声音以及对应的音量变化,也即是将声音视作hotspot.当视角转到该声音热点时,也随之听到声音.官方样例:点击打开链接 本文已经搬迁到下述网址.请点 ...

  10. HDU 5052 Yaoge’s maximum profit 光秃秃的树链拆分 2014 ACM/ICPC Asia Regional Shanghai Online

    意甲冠军: 特定n小点的树权. 以下n每一行给出了正确的一点点来表达一个销售点每只鸡价格的格 以下n-1行给出了树的侧 以下Q操作 Q行 u, v, val 从u走v,程中能够买一个鸡腿,然后到后面卖 ...