SQL Server 一些使用小技巧

原文:SQL Server 一些使用小技巧

1、查询的时候把某一个字段的值拼接成字符串

以下是演示数据。

第一种方式:使用自定义变量

DECLARE @Names NVARCHAR(128)

SET @Names=‘‘    -- 需要先赋值为空字符串,不然结果会是 null 

SELECT @Names=@Names+S_Name+‘,‘        -- S_Name 类型为字符串类型,如果不能隐示转换,就需要强制转换
FROM Student

SELECT @Names

这种方法有一个好处就是,拼接出来的字符串可以赋值给变量或直接插入表中指定字段,可以适用于存储过程之类的。

第二种方式:转换为 XML 格式

SELECT t.S_Name + ‘,‘
FROM
(
    SELECT S_Name
    FROM Student
) t
FOR XML PATH(‘‘)

使用这种方式有一个缺点就是,不能直接赋值给变量或插入表,适用于查看时使用。

如果想要使之能够赋值给变量或插入表中,那就需要转换一下。如下:

DECLARE @Names NVARCHAR(128)

SET @Names=‘‘

SELECT @Names=
(
    SELECT t.S_Name + ‘,‘
    FROM
    (
        SELECT S_Name
        FROM Student
    ) t
    FOR XML PATH(‘‘),TYPE
).value(‘.‘,‘NVARCHAR(128)‘)

SELECT @Names 

2、查询一个字段同时满足多个条件的方法

举个栗子:比如现在有一些订单,而每一个订单有多个产品,现在我要查出同时具有某几个产品的订单。

再拿学生和课程来举例,一个学生可以选择多门课程,而每一门课程也可以同时被多个学生所选择,那么我现在要查出选择了某几门课程的学生。

下面是演示数据。

现在我要查出同时选择了 C# 和 SQL 课程的学生信息。如下:

  SELECT s.S_Id,s.S_No,s.S_Name
  FROM Student s
  INNER JOIN Student_Course_Relation r ON s.S_Id=r.S_Id
  INNER JOIN Course c ON r.C_Id=c.C_Id
  WHERE c.C_Name=‘C#‘ OR c.C_Name=‘SQL‘
  GROUP BY s.S_Id,s.S_No,s.S_Name
  HAVING COUNT(1) >= ‘2‘            -- 这个数字是根据 where 条件来定

3、SQL Server 实现多行转列

之前也写过一篇博客,SQL Server 使用 Pivot 和 UnPivot 实现行列转换,但是之前都是相对于“单列”的转换,于是最近碰到一个需要两列的问题。最后在网上找了一些相关资料,得出了下面的解决方法。下面先建立一个表,插入一些模拟的数据。如下:

create table OrderDemo
(
    ID        int        not null identity(1,1) primary key,
    CustomerCode    nvarchar(16)    not null,
    OrderCount    int        not null default(0),
    TotalAmount  decimal(13,3)    not null default(0),
    YearDate    nvarchar(8)        null,
    MonthDate    nvarchar(8)        null
)

insert into OrderDemo
(
    CustomerCode,
    OrderCount,
    TotalAmount,
    YearDate,
    MonthDate
)
select ‘A001‘,‘23‘,‘28.650‘,‘2017‘,‘1‘ union all
select ‘A001‘,‘67‘,‘123.123‘,‘2017‘,‘2‘ union all
select ‘A002‘,‘12‘,‘28.320‘,‘2017‘,‘1‘ union all
select ‘A002‘,‘37‘,‘51.221‘,‘2017‘,‘2‘ union all
select ‘A003‘,‘89‘,‘452.200‘,‘2017‘,‘1‘ union all
select ‘A003‘,‘134‘,‘523.210‘,‘2017‘,‘2‘ union all
select ‘A004‘,‘78‘,‘230.220‘,‘2017‘,‘1‘ union all
select ‘A004‘,‘95‘,‘180.567‘,‘2017‘,‘2‘ union all
select ‘A005‘,‘128‘,‘230.789‘,‘2017‘,‘1‘ union all
select ‘A005‘,‘256‘,‘340.450‘,‘2017‘,‘2‘ 

select * from OrderDemo 

以上的数据是模拟的按客户、订单年份和订单月份统计的订单数量和金额,由于年月的时间段非固定的,所以这里使用的是动态sql,下面直接上代码:

declare @strSql nvarchar(1024)
declare @strWhere nvarchar(1024)

set @strWhere=‘‘

-- 用作转换之后的列头
select @strWhere = @strWhere+TitleCount+‘,‘+TitleAmount+‘,‘
from
(
    select distinct ‘[‘+YearDate+‘年‘+MonthDate+‘月‘+‘数量‘+‘]‘ TitleCount,‘[‘+YearDate+‘年‘+MonthDate+‘月‘+‘金额‘+‘]‘ TitleAmount
    from OrderDemo
) t 

-- 去掉最后一个逗号
if(CHARINDEX(‘,‘,REVERSE(@strWhere))=1)
begin
    set @strWhere=SUBSTRING(@strWhere,1,len(@strWhere)-1)
end

set @strSql=‘select *
            from
            (
                select CustomerCode,ComDate+ColumnName ComDate,CountAndAmount
                from
                (
                    select CustomerCode,YearDate+‘‘年‘‘+MonthDate+‘‘月‘‘ ComDate,
                    cast(OrderCount as nvarchar) ‘‘数量‘‘,
                    cast(TotalAmount as nvarchar) ‘‘金额‘‘
                    from OrderDemo
                ) a
                UNPIVOT
                (
                    CountAndAmount for ColumnName
                    IN ([数量],[金额])
                ) b
            ) c
            pivot
            (
                max(CountAndAmount)
                for ComDate
                in (‘+ @strWhere +‘)
            ) d ‘

exec (@strSql) 

结果如下:

既然两列可以这么实现,那么如果在多一列呢,或者多很多列。这里我稍稍修改了一下,多增加了一列进行测试(多列同理),修改之后的代码如下:

create table OrderDemo
(
    ID        int        not null identity(1,1) primary key,
    CustomerCode    nvarchar(16)    not null,
    OrderCount    int        not null default(0),
    ProductCount int  not null default(0),
    TotalAmount  decimal(13,3)    not null default(0),
    YearDate    nvarchar(8)        null,
    MonthDate    nvarchar(8)        null
)

insert into OrderDemo
(
    CustomerCode,
    OrderCount,
    ProductCount,
    TotalAmount,
    YearDate,
    MonthDate
)
select ‘A001‘,‘23‘,‘35‘,‘28.650‘,‘2017‘,‘1‘ union all
select ‘A001‘,‘67‘,‘75‘,‘123.123‘,‘2017‘,‘2‘ union all
select ‘A002‘,‘12‘,‘18‘,‘28.320‘,‘2017‘,‘1‘ union all
select ‘A002‘,‘37‘,‘42‘,‘51.221‘,‘2017‘,‘2‘ union all
select ‘A003‘,‘89‘,‘98‘,‘452.200‘,‘2017‘,‘1‘ union all
select ‘A003‘,‘134‘,‘150‘,‘523.210‘,‘2017‘,‘2‘ union all
select ‘A004‘,‘78‘,‘99‘,‘230.220‘,‘2017‘,‘1‘ union all
select ‘A004‘,‘95‘,‘102‘,‘180.567‘,‘2017‘,‘2‘ union all
select ‘A005‘,‘128‘,‘138‘,‘230.789‘,‘2017‘,‘1‘ union all
select ‘A005‘,‘256‘,‘280‘,‘340.450‘,‘2017‘,‘2‘ 

select * from OrderDemo 

declare @strSql nvarchar(1024)
declare @strWhere nvarchar(1024)

set @strWhere=‘‘

-- 用作转换之后的列头
select @strWhere = @strWhere+TitleCount+‘,‘+TitleAmount+‘,‘+TitleProduct+‘,‘
from
(
    select distinct ‘[‘+YearDate+‘年‘+MonthDate+‘月‘+‘数量‘+‘]‘ TitleCount,
    ‘[‘+YearDate+‘年‘+MonthDate+‘月‘+‘金额‘+‘]‘ TitleAmount,
    ‘[‘+YearDate+‘年‘+MonthDate+‘月‘+‘产品数量‘+‘]‘ TitleProduct
    from OrderDemo
) t 

-- 去掉最后一个逗号
if(CHARINDEX(‘,‘,REVERSE(@strWhere))=1)
begin
    set @strWhere=SUBSTRING(@strWhere,1,len(@strWhere)-1)
end

set @strSql=‘select *
            from
            (
                select CustomerCode,ComDate+ColumnName ComDate,CountAndAmount
                from
                (
                    select CustomerCode,YearDate+‘‘年‘‘+MonthDate+‘‘月‘‘ ComDate,
                    cast(OrderCount as nvarchar) ‘‘数量‘‘,
                    cast(TotalAmount as nvarchar) ‘‘金额‘‘,
                    cast(ProductCount as nvarchar) ‘‘产品数量‘‘
                    from OrderDemo
                ) a
                UNPIVOT
                (
                    CountAndAmount for ColumnName
                    IN ([数量],[金额],[产品数量])
                ) b
            ) c
            pivot
            (
                max(CountAndAmount)
                for ComDate
                in (‘+ @strWhere +‘)
            ) d ‘

exec (@strSql) 

PS:需要注意的是当需要转换的列的数据类型不同时需要转换为同一种类型,比如这里的 “数量、金额、产品数量”。

4、在子查询中使用 Order By

比如,我现在有这样一些数据。如下:

我现在想要使用子查询按字段 “Stu_Age” 排序,那么就有了如下代码:

可以看见这样是有错误的,那么下面有两种解决办法。

第一种: row_number() over() 排名开窗函数

  select *
  from
  (
      select [StudentID],Stu_FullName,Stu_Age,Stu_Address,Stu_Phone,
      ROW_NUMBER() over(order by Stu_Age) RowNum
      from Student
   ) t 

第二种:TOP 100 PERCENT,英语比较好的朋友就知道 percent 就是百分比的意思,结果显而易见。top 100 percent 就表示百分之百,即全部的数据。

  select *
  from
  (
      select top 100 percent [StudentID],Stu_FullName,Stu_Age,Stu_Address,Stu_Phone
      from Student
      order by Stu_Age
   ) t 

其实我个人的话还是喜欢第一种方式,第二种也是偶尔看到的。

原文地址:https://www.cnblogs.com/lonelyxmas/p/8994430.html

时间: 2024-08-05 13:23:07

SQL Server 一些使用小技巧的相关文章

SQL Server中的小技巧(重复、替换、截取、去空格、去小数点后的位数)

PS:随笔写的在SQL Server中要用到的 (重复.替换.截取.去空格.去小数点后的位数) /*---------------------------重复--------------------------------*/ --重复字符串 返回[abc#abc#abc#] select replicate('abc#', 3); /*---------------------------替换--------------------------------*/ --替换字符串 将e替换成E 返

sql server 之函数小技巧 && 整数类型为空是用空字符串替代实现

1.判空函数 说明:使用指定的替换值替换 NULL. 语法:ISNULL ( check_expression , replacement_value ) 参数: check_expression:将被检查是否为 NULL 的表达式.check_expression 可以为任何类型. replacement_value:当 check_expression 为 NULL 时要返回的表达式.replacement_value 必须是可以隐式转换为 check_expresssion 类型的类型.

SQL Server 2008索引使用技巧

微软MVP及畅销书<Hitchhiker's Guide SQL Server>的作者Bill Vaughn简要给出了SQL Server 2008的索引使用技巧.该主题基于Kimberly Tripp和Paul Randall(这两位是SQL Server高可用性和性能方面的专家)的建议. 下面是主要的建议: ·页(page)密度 优化行大小:SQL Server 2005(及后续版本)支持8k的列.这意味着一行可以超过80k大小.这有意义么?哦,通常情况下没有.对行大小的管理与效率同样重要

SQL Server数据库性能优化技巧

查询速度慢的原因很多,常见如下几种: 1.没有索引或者没有用到索引: 2.I/O吞吐量小,形成了瓶颈效应: 3.内存不足: 4.网络速度慢: 5.查询出的数据量过大: 6.锁或者死锁: 7.返回了不必要的行和列: 8.查询语句不好,没有优化. 可以通过如下方法来优化查询: 硬件/网络方面 1.升级硬件. 2.提高网速. 3.扩大服务器的内存. 4.增加服务器CPU个数. 5.把数据.日志.索引放到不同的I/O设备上. 6.DB Server和APP Server分离. 7.应用分布式分区视图.

解答关于.NET Core操作SQL Server的一些小问题

我以前没有关注过这个问题,是因为我在项目中通常使用的bean,无论是service层的,还是dao层的,都是没有状态的bean,里面只有方法,没有成员变量.在使用这样的bean的时候,多个线程访问同一个bean不会产生线程安全问题. 数据库运维中盛传一个小段子,我误删除了数据库,改怎么办?有备份还原备份,没有备份就准备简历!听起来有趣但发生在谁身上,谁都笑不起来. 后面每搭建一个新的服务都需要在keystone中执行四种操作:1.建租户 2.建用户 3.建角色 4.做关联后面所有的服务公用一个租

Windows Server 2008 R2 小技巧 (转)

一些 Windows Server 2008 R2 的小技巧,包括启用「God Mode (上帝模式)」.添加「快速启动」工具栏.启用桌面「个性化」服务.停用「密碼複雜性」要求,对老程序员熟悉新版的 Windows Server 可能有帮助. --------------------------------------------------------------------------------------------------------------------------------

Sql Server常用函数及技巧

使用Sql Server好长时间了,今天特别想总结一下,算是回顾吧! 常用函数: 1. ISNULL(columnName, '') 先判断该字段是否为空,如果为空,返回''; 否则返回该字段本来的值. 2. DATEDIFF(datepart,startdate,enddate) 不罗嗦,直接参考 链接 3. 实用语句: 1. 有时候项目中定义的储存过程比较多,需要确定某一个表被哪些stored procedure使用了,可以有如下两种方法: a. SSMS界面上,选中要查的表,右键,点击查找

sql中的一些小技巧

在sql中经常要用到字符串的连接操作: 在oracle和mysql中都有contact()函数,只有,sqlserver没有,不过,这三个数据库都支持:+ 来连接字符串! 在mysql中,有个不全补零的函数: select LPAD('2',3,'0'); 在sql server中,我们完全可以使用print 来打印一个数据 print 3+3; 任何一个数据库,最好的,也是最牛逼的教材,就是它的文档,读完文档,整个世界就清晰了

SQL Server的一些小问题

一.SQL Server远程调用失败 解决办法:在控制面板-程序和功能中卸载"Microsoft SQL Server 2012 Express LocalDB",具体版本根据你安装的VS版本决定,我的是VS2012 (亲测可用) 二.SQL Server不允许保存修改 解决办法: 1.启动SQL Server 2008 Management Studio"工具菜单->选项"打开选项对话框 2.左侧目录树选择"设计器"(有的上面是desig