• SQL Server 中master..spt_values的应用


    SQL Server 中master..spt_values的应用

    今天在做数据分析报表的时候遇到一个这样的问题。

    表结构如下。
    部门编码、部门名称、部门人员ID(中间用逗号分割)

    我想通过和人员表链接,查询出一个新的数据集,查询出的结果集格式如下:
    人员信息(ID或者姓名)、部门编码、部门名称

    以前都是通过程序遍历拆分表字段组成新的集合字段,然后在结合SQL语句查询出结果集,但是这个报表要求只能通过SQL语句实现,以前记得可以通过写字段分割函数再结合游标实现。然而今天在网上无意间找到一个新的方法。用“master..spt_values”来实现,具体实现方法见下面实例1感觉这个东西太好用了。把网上的实例都整理了一下,希望各路大神批评指教,也希望大家继续把这方面的应用贴上.

    select number from master..spt_values with(nolock) where type='P'
    /**解释:master..spt_values表的字段值为P的对应number字段值是从0-2047*/ 
      
      
    --1.将字符串转换为列显示 
      
    if object_id('tb') is not null drop table tb 
    go 
    create table tb([编号] varchar(3),[产品] varchar(2),[数量] int,[单价] int,[金额] int,[序列号] varchar(8)) 
    insert into tb([编号],[产品],[数量],[单价],[金额],[序列号]) 
    select '001','AA',3,5,15,'12,13,14' union all
    select '002','BB',8,9,13,'22,23,24'
    go 
    select [编号],[产品],[数量],[单价],[金额] 
    ,substring([序列号],b.number,charindex(',',[序列号]+',',b.number)-b.number) as [序列号] 
    from tb a with(nolock),master..spt_values b with(nolock) 
    where b.number>=1 and b.number<len(a.[序列号]) and b.type='P'
    and substring(','+[序列号],number,1)=','
    go 
    drop table tb 
    go 
    /** 
    编号   产品   数量          单价          金额          序列号 
    ---- ---- ----------- ----------- ----------- -------- 
    001  AA   3           5           15          12 
    001  AA   3           5           15          13 
    001  AA   3           5           15          14 
    002  BB   8           9           13          22 
    002  BB   8           9           13          23 
    002  BB   8           9           13          24 
    */ 
    ---------- 
      
    --2.第四个逗号之前的字符串 
    declare @str varchar(100) 
    set @str='10,102,10254,103265,541,2154,41,156'
    ;with cte as( 
    select left(@str,number-1) as ss,row_number()over(order by getdate()) as xh 
    from master..spt_values with(nolock)  
    where number>=1 and number<=len(@str+',') and type='P' 
    and substring(@str+',',number,1)=','
    )select ss from cte where xh=4 
    /** 
    ss 
    ------------------- 
    10,102,10254,103265 
    */ 
    ---------- 
      
      
    --3.找出两句话中相同的汉字 
    declare @Lctext1 varchar(100) 
    declare @Lctext2 varchar(100) 
    set @Lctext1='我们都是来自五湖四海的朋友'
    set @Lctext2='朋友多了路真的好走吗'
    select substring(@Lctext2,number,1) as value 
    from master..spt_values with(nolock) 
    where type='P' and number>=1 and number<=len(@Lctext2) 
    and charindex(substring(@Lctext2,number,1),@Lctext1,number)>1 
    /** 
    value 
    ----- 
    朋 
    友 
    的 
    */ 
    --------- 
      
      
    --4.提取两个日期之间的所有月份 
    if object_id('tb') is not null drop table tb 
    go 
    create table tb(id int identity(1,1),startDate varchar(10),endDate varchar(10)) 
    insert into tb(startDate,endDate) select '2013-01-01','2013-09-25'
    go 
    declare @startDate varchar(10) 
    declare @endDate varchar(10) 
    select @startDate=startDate,@endDate=endDate from tb with(nolock) 
    select convert(varchar(7),dateadd(mm,number,@startDate),120) as [月份] 
    from master..spt_values with(nolock) 
    where type='P' and number>=0 
    and dateadd(mm,number,@startDate)<=@endDate 
    go 
    drop table tb 
    go 
    /** 
    月份 
    ------- 
    2013-01 
    2013-02 
    2013-03 
    2013-04 
    2013-05 
    2013-06 
    2013-07 
    2013-08 
    2013-09 
    */ 
    --------- 
      
      
    --5.求一个日期所在月份的所有日期 
    declare @date datetime 
    set @date='2013-08-31'
    select convert(char(7),@date,120)+'-'+right('0'+convert(varchar(2),number),2) as [日期格式1] 
    ,ltrim(year(@date))+right(100+month(@date),2)+right('0'+ltrim(number),2) as [日期格式2] 
    from master..spt_values with(nolock) 
    where type='P' and number>=1 
    --and number<=datediff(dd,@date,dateadd(mm,1,@date)) --对于mssql而言该语句不试用于2013-08-31的情况,这时由于9月没有31号,固计算出来的天数是30天 
    and number<=datediff(dd,convert(char(7),@date,120)+'-01',convert(char(7),dateadd(mm,1,@date),120)+'-01')--转换为1号来计算天数 
    /** 
    日期格式1       日期格式2 
    ----------- -------------------- 
    2013-08-01  20130801 
    2013-08-02  20130802 
    2013-08-03  20130803 
    2013-08-04  20130804 
    2013-08-05  20130805 
    2013-08-06  20130806 
    2013-08-07  20130807 
    2013-08-08  20130808 
    2013-08-09  20130809 
    2013-08-10  20130810 
    2013-08-11  20130811 
    2013-08-12  20130812 
    2013-08-13  20130813 
    2013-08-14  20130814 
    2013-08-15  20130815 
    2013-08-16  20130816 
    2013-08-17  20130817 
    2013-08-18  20130818 
    2013-08-19  20130819 
    2013-08-20  20130820 
    2013-08-21  20130821 
    2013-08-22  20130822 
    2013-08-23  20130823 
    2013-08-24  20130824 
    2013-08-25  20130825 
    2013-08-26  20130826 
    2013-08-27  20130827 
    2013-08-28  20130828 
    2013-08-29  20130829 
    2013-08-30  20130830 
    2013-08-31  20130831 
    */ 
    --------- 
      
      
    --6.根据给定时间为基准以2小时为划分,得出一天划分出的时间段 
    declare @time varchar(5) 
    set @time='11:13'
    select ltrim(a.number)+right(@time,3)+'-'+ltrim(b.number)+right(@time,3) as [划分结果] 
    from master..spt_values a with(nolock),master..spt_values b with(nolock) 
    where a.type='P' and b.type='P'
    and a.number>=left(@time,2) and b.number<=24 
    and a.number+2=b.number 
    /** 
    划分结果 
    ----------------------------------- 
    11:13-13:13 
    12:13-14:13 
    13:13-15:13 
    14:13-16:13 
    15:13-17:13 
    16:13-18:13 
    17:13-19:13 
    18:13-20:13 
    19:13-21:13 
    20:13-22:13 
    21:13-23:13 
    22:13-24:13 
    */ 
    --------- 
      
      
    --7.将字符串显示为行列 
    if object_id('tb') is not null drop table tb 
    create table tb(id int identity(1,1),s nvarchar(100)) 
    insert into tb(s) select '车位地址1,车位状况1|车位地址2,车位状况2|车位地址n,车位状况n'
    ;with cte as( 
    select substring(s,number,charindex('|',s+'|',number)-number) as ss 
    from tb with(nolock),master..spt_values with(nolock) 
    where type='P' and number>=1 and number<=len(s) 
    and substring('|'+s,number,1)='|'
    )select left(ss,charindex(',',ss)-1)as s1,substring(ss,charindex(',',ss)+1,len(ss))as s2 from cte 
    drop table tb 
    /** 
    s1             s2 
    ----------- ------------ 
    车位地址1      车位状况1 
    车位地址2      车位状况2 
    车位地址n      车位状况n 
    */
  • 相关阅读:
    二维数组转换
    二维数组转换
    二分法原理
    二维数组举例
    二分法原理
    二维数组举例
    二分法原理
    二分法原理
    linux中BIND服务程序安全的加密传输TSIG机制
    linux系统中部署DNS从服务器
  • 原文地址:https://www.cnblogs.com/grj001/p/12224175.html
Copyright © 2020-2023  润新知