• SQL的一些经典算法


    1 SQL分页查询,每页10个数据,取第三页

    A) 如果有id列

    select top(10)  * from Spider_Hotel

    where Spider_Hotel.HotelId not in

    ( select top (10*2) Spider_Hotel.HotelId from Spider_Hotel)

    B) 如果没有id列

    select top (10) * from

    (select ROW_NUMBER() over (order by Name) as Row,* from Spider_Hotel)

     a

    where Row>10*2

    C) 如果有id列

    select top (10) * from Spider_Hotel

    where HotelId >(select max(HotelId)

    from (select top (10*2) HotelId from Spider_Hotel order by HotelId) as a

    )

     

    2,数据库删除重复记录。

    a, 如果有id列 a,b,c 重复

    Delete  from table  where id not in (select max (id) from table group a,b,c)

    b,  如果没有id列a,b,c 重复 .用row_number() over 函数,制造个Id列

       With Tab as

         Select  row_number() over (order by a) as Row,a,b,c from table

    Delete from Tab

    Where  Row not in (selete max(Row) from Tab group a,b,c)

    3,Count函数。

      SELECT COUNT(*),COUNT(FNumber),COUNT(FName) FROM T_Employee

    COUNT(*)统计的是结果集的总条数,而

    COUNT(FName)统计的则是除了结果集中FName 不为空值(也就是不等于NULL)的记录的总

    条数,如果Fname有为空COUNT(*) 不等于COUNT(FNumber)

    4,求一公司年龄在20-30,40-60岁这两个年龄段的人数,行列转换

    select SUM(Young) as Young ,SUM(Old) as Old from (

      select

      Users_age,

      sum(case when Users_age between 1 and 3 then 1 else 0 end) as Young,

      sum(case when Users_age between 4 and 6then 1 else 0 end) as Old

    from Users

    group by Users_age) as s

    //  显示名字,不显示人数,我感觉数据库语句是一个一个判断下去的

    select

      years,

      case when age between 20 and 30 then name else '---' end as [20-30],

      case when age between 30 and 40 then name else '---' end as [30-40],

      case when age between 40 and 50 then name else '---' end as [40-50]

    from info

    group by years,name,age

    5,连续三天的记录   (查询连续三天抽取同一家酒店同一入住时间的免费房的人员记录)

    select Member_Code from

    dbo.Member a where

    exists

    (

       select * from Member b

       where b.Register_Date = DATEADD(D,1,a.Register_Date) and a.Member_Code=b.Member_Code

    )

    and

    exists

    (

       select * from Member b

       where b.Register_Date = DATEADD(D,2,a.Register_Date) and a.Member_Code=b.Member_Code

    )

    group by Member_Code

    6,查询表结构   (查询一个数据库所有的数据库表 字段类型 字段大小)

    --查询表结构

    select Dense_Rank() over (order by o.name) as table_order, ROW_NUMBER() over (partition by o.id order by o.name) as column_order,

    o.name as table_name, c.name as column_name, t.name+'['+ convert(varchar, c.[length])+']' as column_type

    from sysobjects o inner join syscolumns c

    inner join systypes t on c.xusertype=t.xusertype

    on o.id=c.id

    where o.xtype='U'

    order by o.name

    --查询数据库表

    select * from dbo.sysobjects

    where sysobjects.xtype ='U'

    --查询数据库列

    select * from syscolumns

    where id=21575115

    7,截止今天的销售额  (一个超市每天都有营业额。列出每天的营业额和截止到每天的总营业额。)

    (比如,第一天 营业额 10 总营业额 10,第二天 营业额20 总营业额 30;第二天 营业额 10 总营业额 40)

    select dates,(select SUM(moneys) from Table as TT

    where TT.dates <= T.dates)  from Table as T

    8,全局临时表,防止用户两地登录。

    --全局临时表防止用户地登录,但是如果用户量大,这很可能消耗大量资源。

    --用户登录,就根据用户Id创建个临时表,如果用户账户异地登录,就会发现

    --这张临时表已经存在,返回,提示登录不成功。用户退出系统后,临时表自动消失。

    alter proc gp_findtemptable

    @v_userid varchar(6),@i_out int output

    as

    declare @v_sql varchar(100)

    if object_id('tempdb.dbo.##'+@v_userid) is null

    begin

    set @v_sql = 'create table ##'+@v_userid+'(userid varchar(6))'

    exec (@v_sql)

    set @i_out = 0

    end

    else

    set @i_out = 1

    declare @I int

    exec gp_findtemptable 'T00001',@I output

    select @I

    9,查找指定节点的所有子节点的子节点。

    create table os(id int,parentid int,desn varchar(10))

    --自己不能是自己的节点,否则进入死循环。

    alter function f_cid(@id int)

    returns varchar(500)

    as

    begin

      declare @t table(id int,desn varchar(10),parentid int,lev int)

      declare @lev int

      set @lev=1

      insert into @t select *,@lev from os where id=@id

      while(@@rowcount>0)

      begin

      set @lev=@lev+1

      insert into @t select a.*,@lev from os a,@t b

      where a.parentid=b.id and b.lev=@lev-1

      end

      declare @cids varchar(500)

      select @cids=isnull(@cids+',','')+ltrim(id) from @t order by lev

      return @cids

    end

    go

    执行查询

    select *,ids=dbo.f_cid(id) from os

    10, 排名开窗函数 利用ROW_NUMBER() over(partition by 列名order by 列名)进行分组后排序。

    --统计每一个客户最近下的订单是第几次下的订单。

    with tabs as

     (

     select ROW_NUMBER() over(partition by customerID  order by totalPrice) as rows,customerID,totalPrice, DID from OP_Order

     )

     select MAX(rows) as '下单次数',customerID from tabs group by customerID

    --统计分组后的前2名。

    with tab as

    (

    select Id,desn,parentid,ROW_NUMBER() over(partition by desn order by parentid) as rowss    from dbo.os

    group by Id,desn,parentid

    )

    select * from tab where rowss>=2

    --统计筛选出客户第一次下的订单。。

     with tabs as

     (

     select ROW_NUMBER() over(partition by customerID  order by insDT) as rows,* from OP_Order

     )

     select * from tabs where rows = 1

    11, 聚合开窗函数 使用over子句与rows_number()以及聚合函数进行使用,可以进行编号以及各种操作。而且利用over子句的分组效率比group by子句的效率更高。

     

    --在订单表(order)中统计中,生成这么每一条记录都包含如下信息:“所有订单的总和(AllTotalPrice)”、“每一位客户的所有订单的总(cusTotalPrice)”、”每一单的金额(totalPrice)“,”每一个客户订单的平均金额(avgCusprice)“,”所有客户的所有订单的平均金额(avgTotalPrice)“,"订单金额最小值(MinTotalPrice)","客户订单金额最小值(MinCusPrice)","订单金额最大值(MaxTotalPrice)","客户订单金额最大值(MaxCusPrice)","客户所购的总额在所有的订单中总额的比例(CusAllPercent)","每一订单的金额在每一位客户总额中所占的比例(cusToPercent)"。

    with tabs as

      (

       select

      customerID,

      SUM(totalPrice) over() as AllTotalPrice,

      SUM(totalPrice) over(partition by customerID) as cusTotalPrice,

      AVG(totalPrice) over(partition by customerID) as avgCusprice,

      AVG(totalPrice) over() as avgTotalPrice,

      MIN(totalPrice) over() as MinTotalPrice,

      MIN(totalPrice) over(partition by customerID) as MinCusPrice,

      MAX(totalPrice) over() as MaxTotalPrice,

      MAX(totalPrice) over(partition by customerID) as MaxCusPrice,

      totalPrice

      from OP_Order

      )

      select

      customerID,

      AllTotalPrice,

      cusTotalPrice,

      totalPrice,

      avgCusprice,

      avgTotalPrice,

      MinTotalPrice,

      MinCusPrice,

      MaxTotalPrice,

      MaxCusPrice,

      cusTotalPrice/AllTotalPrice as CusAllPercent,

      totalPrice/cusTotalPrice as cusToPercent

      from tabs

    12 通用表达式:CTE(Common Table Expression)实现递归查询

    With AA as

    (

    select Id,SupplierName, ParentId,0 as levels from Supplier where ParentId='0'

    union all select BB.Id,BB.SupplierName, BB.ParentId,R.levels+1 as levels from Supplier as BB

    join AA as R

    on BB.ParentId=R.Id

    )

    select * from AA

    --通用表达式:CTE(Common Table Expression)实现递归查询

  • 相关阅读:
    上下文相关协议的学习
    正则模块学习
    Delphi 10.2.3 + Xcode 9.2 开发 IOS 程序,免证书+免越狱,真机调试
    Delphi X10.2 + FireDAC 使用 SQL 语句 UPDATE
    Delphi X10.2 + FireDAC 使用 SQL 语句 INSERT
    Png 图像缩放保持 Alpha 通道
    delphi 10.1 Berlin 中使用自带的 Base64 编码
    delphi 10.1 Berlin 中使用自带的 MD5 校验
    完成 bass 库的频谱显示效果图
    Ubuntu 12.04 LTS 安裝无线网卡驱动
  • 原文地址:https://www.cnblogs.com/AnchorRon/p/2680558.html
Copyright © 2020-2023  润新知