• SQL常用语句简单


    数据库脚本
    USE [Test]
    GO
    /****** Object:  Table [dbo].[Class]    Script Date: 2017/6/29 13:17:14 ******/
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    CREATE TABLE [dbo].[Class](
        [ClassID] [int] NULL,
        [ClassName] [nvarchar](50) NULL
    ) ON [PRIMARY]
    
    GO
    /****** Object:  Table [dbo].[Student]    Script Date: 2017/6/29 13:17:14 ******/
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    CREATE TABLE [dbo].[Student](
        [StuID] [int] NOT NULL,
        [StuName] [nvarchar](50) NULL,
        [StuAge] [int] NULL,
        [ClassID] [int] NULL
    ) ON [PRIMARY]
    
    GO
    INSERT [dbo].[Class] ([ClassID], [ClassName]) VALUES (1, N'班级1')
    GO
    INSERT [dbo].[Class] ([ClassID], [ClassName]) VALUES (2, N'班级2')
    GO
    INSERT [dbo].[Class] ([ClassID], [ClassName]) VALUES (3, N'班级3')
    GO
    INSERT [dbo].[Class] ([ClassID], [ClassName]) VALUES (4, N'班级4')
    GO
    INSERT [dbo].[Class] ([ClassID], [ClassName]) VALUES (5, N'班级5')
    GO
    INSERT [dbo].[Class] ([ClassID], [ClassName]) VALUES (2, N'班级2')
    GO
    INSERT [dbo].[Student] ([StuID], [StuName], [StuAge], [ClassID]) VALUES (1, N'张三', 19, 1)
    GO
    INSERT [dbo].[Student] ([StuID], [StuName], [StuAge], [ClassID]) VALUES (2, N'李四', 18, 1)
    GO
    INSERT [dbo].[Student] ([StuID], [StuName], [StuAge], [ClassID]) VALUES (3, N'王五', 16, 2)
    GO
    INSERT [dbo].[Student] ([StuID], [StuName], [StuAge], [ClassID]) VALUES (4, N'啦啦', 20, 7)
    GO
    INSERT [dbo].[Student] ([StuID], [StuName], [StuAge], [ClassID]) VALUES (5, N'王五2', 16, 2)
    GO
    INSERT [dbo].[Student] ([StuID], [StuName], [StuAge], [ClassID]) VALUES (5, N'王五3', 16, 2)
    GO
    INSERT [dbo].[Student] ([StuID], [StuName], [StuAge], [ClassID]) VALUES (5, N'王五3', 16, 2)
    GO
    View Code

    一、排序 

      排序的可以产生序号,所以都可以分页查询

    1、row_number() over(order by 字段)

    SELECT *,ROW_NUMBER() OVER ( ORDER BY s.StuAge) FROM Student AS s
    3    王五     16    2    1
    5    王五2    16    2    2
    5    王五3    16    2    3
    5    王五3    16    2    4
    2    李四     18    1    5
    1    张三     19    1    6
    4    啦啦     20    7    7

    2、row_number() over(PARTITION BY 字段order by 字段)      over中可以分区在编号

    SELECT *,ROW_NUMBER() OVER ( PARTITION BY s.ClassID ORDER BY s.StuAge) FROM Student AS s
    2    李四     18    1    1
    1    张三     19    1    2
    3    王五     16    2    1
    5    王五2    16    2    2
    5    王五3    16    2    3
    5    王五3    16    2    4
    4    啦啦     20    7    1
    3、DENSE_RANK()出现  并列排序 (序号连续)
    --DENSE_RANK()
    SELECT *,DENSE_RANK() OVER ( ORDER BY s.StuAge DESC) FROM Student AS s
    4    啦啦     20    7    1
    1    张三     19    1    2
    2    李四     18    1    3
    3    王五     16    2    4
    5    王五2    16    2    4
    5    王五3    16    2    4
    5    王五3    16    2    4
    4、RANK()   出现并列排序(序号不连续)
    --rank()
    SELECT *,RANK() OVER (ORDER BY s.StuAge ) FROM Student AS s
    3    王五     16    2    1
    5    王五2    16    2    1
    5    王五3    16    2    1
    5    王五3    16    2    1
    2    李四     18    1    5
    1    张三     19    1    6
    4    啦啦     20    7    7
    5、NTILE(INT)     要把查询得到的结果平均分为几组
    --NTILE 要把查询得到的结果平均分为几组,总数/组数=每组数量
    --如果每组数量部位整数  则在第一组多加行   少的话在最后一组减
    SELECT *,NTILE(3) OVER (ORDER BY s.StuAge DESC) FROM Student AS s
    4    啦啦     20    7    1
    1    张三     19    1    1
    2    李四     18    1    1
    3    王五     16    2    2
    5    王五2    16    2    2
    5    王五3    16    2    3
    5    王五3    16    2    3

    二、结果集合并

    1、UNION

    --UNION  去除两个表中重复的行
    SELECT * FROM Student AS s UNION  SELECT * FROM Student
    1    张三     19    1
    2    李四     18    1
    3    王五     16    2
    4    啦啦     20    7
    5    王五2    16    2
    5    王五3    16    2
    View Code

    2、UNION ALL

    --UNION ALL  完全合并,不去除两个表中重复的行
    SELECT * FROM Student AS s UNION ALL  SELECT * FROM Student
    1    张三     19    1
    2    李四     18    1
    3    王五     16    2
    4    啦啦     20    7
    5    王五2    16    2
    5    王五3    16    2
    5    王五3    16    2
    1    张三     19    1
    2    李四     18    1
    3    王五     16    2
    4    啦啦     20    7
    5    王五2    16    2
    5    王五3    16    2
    5    王五3    16    2
    View Code

     三、GROUP BY产生高级汇总结果

    https://msdn.microsoft.com/zh-cn/library/ms175939(v=sql.90).aspx

    小计  合计

    1、WITH CUBE(英文多维数据集)     生成的结果集显示了所选列中值的所有组合的聚合。  

    正常分组

    select 
    s.ClassID,s.StuAge,COUNT(1)
    FROM Class AS c
    inner JOIN Student AS s
    ON s.ClassID = c.ClassID GROUP BY s.ClassID,s.StuAge
    ClassID    StuAge    (无列名)
    2          16         8
    1          18         1
    1          19         1

    with cube 汇总

    --只是在基于GROUP BY 子句创建和汇总分组的可能的组合上有一定差别,CUBE将返回的更多
    --的可能组合。如果在GROUP BY子句中有N个列或者是有N个表达式的话,SQLSERVER在结果集
    --上会返回2的N-1次幂个可能组合。
    select 
    s.ClassID,s.StuAge,COUNT(1)
    FROM Class AS c
    inner JOIN Student AS s
    ON s.ClassID = c.ClassID GROUP BY s.ClassID,s.StuAge WITH CUBE
    ClassID    StuAge    (无列名)
    2          16            8
    NULL       16            8
    1          18            1
    NULL      18         1
    1         19         1
    NULL      19         1
    NULL      NULL         10
    1         NULL         2
    2         NULL         8
        select 
    s.ClassID,s.StuAge,COUNT(1)
    FROM Class AS c
    inner JOIN Student AS s
    ON s.ClassID = c.ClassID GROUP BY CUBE( s.ClassID,s.StuAge)
    ClassID    StuAge    (无列名)
    2    16    8
    NULL    16    8
    1    18    1
    NULL    18    1
    1    19    1
    NULL    19    1
    NULL    NULL    10
    1    NULL    2
    2    NULL    8
    View Code
        select 
    s.ClassID,s.StuAge,COUNT(1)
    FROM Class AS c
    inner JOIN Student AS s
    ON s.ClassID = c.ClassID GROUP BY CUBE( s.ClassID),s.StuAge
    ClassID    StuAge    (无列名)
    2    16    8
    NULL    16    8
    1    18    1
    NULL    18    1
    1    19    1
    NULL    19    1
    View Code

    2、WITH ROLLUP(英文汇总)  生成的结果集显示了所选列中值的某一层次结构的聚合

     https://msdn.microsoft.com/zh-cn/library/ms189305(v=sql.90).aspx

    ROLLUP就是将GROUP BY后面的第一列名称求总和,而其他列并不要求而CUBE则会将每一个列名称都求总和 
    select 
    s.ClassID,s.StuAge,COUNT(1)
    FROM Class AS c
    inner JOIN Student AS s
    ON s.ClassID = c.ClassID GROUP BY s.StuAge,s.ClassID WITH ROLLUP
    ClassID    StuAge    (无列名)
    2        16    8
    NULL    16    8
    1        18    1
    NULL    18    1
    1        19    1
    NULL    19    1
    NULL    NULL    10
    View Code
    select 
    s.ClassID,s.StuAge,COUNT(1)
    FROM Class AS c
    inner JOIN Student AS s
    ON s.ClassID = c.ClassID GROUP BY s.ClassID,s.StuAge WITH ROLLUP
    ClassID    StuAge    (无列名)
    1        18        1
    1        19        1
    1      NULL      2
    2        16        8
    2    NULL        8
    NULL    NULL        10    
    View Code

    四、GROUPING SETS和GROUPING函数

    1、GROUPING SETS可以简化大量的UNION

      插叙:

    SQL统计函数
    
    https://docs.microsoft.com/zh-cn/sql/t-sql/functions/aggregate-functions-transact-sql
    View Code

      使用union合并

    SELECT c.ClassName,NULL,COUNT(1)
      FROM Class AS c INNER JOIN Student AS s ON s.ClassID = c.ClassID GROUP BY c.ClassName
      UNION
    SELECT  NULL,s.StuAge,COUNT(1)
      FROM Class AS c INNER JOIN Student AS s ON s.ClassID = c.ClassID GROUP BY s.StuAge
    ClassName    (无列名)    (无列名)
    NULL    16    8
    NULL    18    1
    NULL    19    1
    班级1    NULL    2
    班级2    NULL    8

      对应执行计划

      使用grouping sets(列明,表达式,(列名1,列名2...))       可以是列名  表达式,多个组合。

    SELECT c.ClassName,s.StuAge,COUNT(1)
      FROM Class AS c INNER JOIN Student AS s ON s.ClassID = c.ClassID GROUP BY GROUPING SETS(s.StuAge,c.ClassName)
    ClassName    StuAge    (无列名)
    班级1    NULL    2
    班级2    NULL    8
    NULL    16    8
    NULL    18    1
    NULL    19    1

    GROUPING SETS不仅仅只是语法糖.而是从执行原理上做出了改变.(可以查看这两者的执行计划,第二次表扫描增多,第一次少,但是前面就行union操作。)

    2、grouping sets和grouping 联合使用

     grouping(列名或者表达式)  grouping(列名1,列名2...)  返回 0   1,必须和group by一起使用。参数必须在GROUPBY里面的

    MSDN:Is a column or an expression that contains a column in a GROUP BY clause. 

    SELECT CASE    WHEN GROUPING(c.ClassName)=0 THEN c.ClassName ELSE '' end as ClassName,s.StuAge,COUNT(1)
      FROM Class AS c INNER JOIN Student AS s ON s.ClassID = c.ClassID GROUP BY GROUPING SETS(s.StuAge,c.ClassName)
    ClassName    StuAge    (无列名)
    班级1    NULL    2
    班级2    NULL    8
    空      16    8
    空      18    1
    空      19    1

    3、GROUPING_ID

         GROUPING_ID (<column_expression> [ ,...n ])  也可以是组合(根据groupingsets 里面的组合),作用:计算分组等级

      SELECT s.StuAge,s.ClassID,COUNT(1),grouping_id(s.StuAge,s.ClassID) AS c FROM Student AS s GROUP BY cube(s.StuAge,s.ClassID) ORDER BY  c
    StuAge    ClassID    (无列名)    c
    18    1    1    0
    19    1    1    0
    16    2    4    0
    20    7    1    0
    16    NULL    4    1
    18    NULL    1    1
    19    NULL    1    1
    20    NULL    1    1
    NULL    2    4    2
    NULL    1    2    2
    NULL    7    1    2
    NULL    NULL    7    3
    View Code
      SELECT s.StuAge,s.ClassID,COUNT(1),grouping_id(s.StuAge) AS c FROM Student AS s GROUP BY cube(s.StuAge,s.ClassID) ORDER BY  c
    StuAge    ClassID    (无列名)    c
    18    1    1    0
    19    1    1    0
    16    2    4    0
    16    NULL    4    0
    18    NULL    1    0
    19    NULL    1    0
    20    NULL    1    0
    20    7    1    0
    NULL    7    1    1
    NULL    NULL    7    1
    NULL    2    4    1
    NULL    1    2    1
    View Code
    SELECT CASE    WHEN GROUPING(c.ClassName)=0 THEN c.ClassName ELSE '' end as ClassName,s.StuAge,COUNT(1),grouping_id(s.StuAge,c.ClassName) 
      FROM Class AS c INNER JOIN Student AS s ON s.ClassID = c.ClassID GROUP BY GROUPING SETS(s.StuAge,c.ClassName)
    ClassName    StuAge    (无列名)    (无列名)
    班级1    NULL    2    2
    班级2    NULL    8    216    8    118    1    119    1    1
    View Code
    SELECT CASE    WHEN GROUPING(c.ClassName)=0 THEN c.ClassName ELSE '' end as ClassName,s.StuAge,COUNT(1),grouping_id(s.StuAge) 
      FROM Class AS c INNER JOIN Student AS s ON s.ClassID = c.ClassID GROUP BY GROUPING SETS(s.StuAge,c.ClassName)
    ClassName    StuAge    (无列名)    (无列名)
    班级1    NULL    2    1
    班级2    NULL    8    116    8    018    1    019    1    0
    View Code

    只有一个分组等级

    SELECT s.StuAge,s.ClassID,COUNT(1),grouping_id(s.StuAge) AS c FROM Student AS s GROUP BY s.StuAge,s.ClassID ORDER BY  c
    
    
    
    
        SELECT s.StuAge,s.ClassID,COUNT(1),grouping_id(s.StuAge,s.ClassID) AS c FROM Student AS s GROUP BY s.StuAge,s.ClassID ORDER BY  c

    两个sql结果一样

    StuAge    ClassID    (无列名)    c
    18    1    1    0
    19    1    1    0
    16    2    4    0
    20    7    1    0
    View Code

    思考:group 里面分组,

    单一条件分组,group by 列1,列2

    多项分组,例如 group by  grouping sets(列1,列2,(列3,列4)),GROUP BY cube(s.StuAge,s.ClassID)

    五、WITH AS   公用表表达式(CTE)(common table expression)    也叫做子查询部分

    MSDN详解:https://docs.microsoft.com/zh-cn/sql/t-sql/queries/with-common-table-expression-transact-sql  (还是这帮老外厉害)

    http://wudataoge.blog.163.com/blog/static/80073886200961652022389/

    1、语法格式

    [ WITH <common_table_expression> [ ,n ] ] 
    <common_table_expression>::= 
            expression_name [ ( column_name [ ,n ] ) ] 
        AS 
            ( CTE_query_definition )

    如果WITH AS短语所定义的表名被调用两次以上,则优化器会自动将
    WITH AS短语所获取的数据放入一个TEMP表里,如果只是被调用一次,则不会。而提示materialize则是强制将WITH AS
    短语里的数据放入一个全局临时表里。很多查询通过这种方法都可以提高速度。

     2、用法

    DECLARE @cname NVARCHAR(50),@cclass NVARCHAR(50)
    SET @cname='%名%';
    SET @cclass='%班级%';
    WITH stu AS (SELECT * FROM Student AS s WHERE s.StuName LIKE @cname),
         claa AS    (SELECT * FROM Class AS c WHERE c.ClassName LIKE @cclass)
    SELECT * FROM stu st INNER JOIN claa AS s ON st.ClassID =s.ClassID
    --下面一句不能执行
    SELECT * FROM claa
    StuID    StuName    StuAge    ClassID    ClassID    ClassName
    8         名字8        8           1         1        班级1

    3、递归

    数据库脚本

    USE [Test]
    GO
    /****** Object:  Table [dbo].[Deparment]    Script Date: 2017/6/30 11:23:18 ******/
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    CREATE TABLE [dbo].[Deparment](
        [ID] [int] NULL,
        [PID] [int] NULL,
        [Name] [nvarchar](50) NULL
    ) ON [PRIMARY]
    
    GO
    INSERT [dbo].[Deparment] ([ID], [PID], [Name]) VALUES (1, NULL, N'永赢基金')
    GO
    INSERT [dbo].[Deparment] ([ID], [PID], [Name]) VALUES (2, 1, N'人力资源')
    GO
    INSERT [dbo].[Deparment] ([ID], [PID], [Name]) VALUES (3, 1, N'财务部')
    GO
    INSERT [dbo].[Deparment] ([ID], [PID], [Name]) VALUES (4, 2, N'人力主管')
    GO
    INSERT [dbo].[Deparment] ([ID], [PID], [Name]) VALUES (5, 2, N'人力员工')
    GO
    INSERT [dbo].[Deparment] ([ID], [PID], [Name]) VALUES (6, 5, N'人力大员工')
    GO
    INSERT [dbo].[Deparment] ([ID], [PID], [Name]) VALUES (7, 5, N'人力小员工')
    GO
    INSERT [dbo].[Deparment] ([ID], [PID], [Name]) VALUES (8, 1, N'监察稽核部')
    GO
    View Code

    递归语句

    WITH dep AS (SELECT *,0 AS DepLeavel FROM Deparment WHERE ID=1
    UNION ALL

    SELECT d.*,dtemp.DepLeavel+1 FROM dep AS dtemp INNER JOIN Deparment AS d ON d.PID=dtemp.ID
    )
    SELECT * FROM dep AS d OPTION (MAXRECURSION 3)

    ID    PID    Name    DepLeavel
    1    NULL    永赢基金    0
    2    1    人力资源    1
    3    1    财务部    1
    8    1    监察稽核部    1
    4    2    人力主管    2
    5    2    人力员工    2
    6    5    人力大员工    3
    7    5    人力小员工    3
    View Code
  • 相关阅读:
    如何用C语言写一个基于服务器和客户端(TCP)
    如何把C++的源代码改写成C代码?
    可自定义的超链接控件
    一个XP风格的下拉分离按钮
    GroupControl
    带有工具提示和/或位图资源的按钮
    动态更改按钮图像
    一键启用/禁用一组控件
    粘性Snap-to-Center控制
    WinForm ImageButton
  • 原文地址:https://www.cnblogs.com/wudequn/p/7093539.html
Copyright © 2020-2023  润新知