SQL分组排序,根据类型取值

合集下载

sqlserver分组排序并取出每组中的第一条数据

sqlserver分组排序并取出每组中的第一条数据

sqlserver分组排序并取出每组中的第⼀条数据
使⽤SQL Server数据库在【分组排序并取出每组中的第⼀条数据】的场景下,很容易想到的是使⽤GROUP BY分组⼦句配合聚合函数。

举个简单的例⼦,有⼀个YANGGBS表,表中有NAME和AGE两个字段,要求统计出每个NAME的最⼤AGE。

SELECT AA.*
FROM YANGGBS AA
INNER JOIN (
SELECT NAME, MAX(AGE)
FROM YANGGBS
GROUP BY NAME
) BB
ON =
另外⼀种⽅法就是使⽤开窗函数(分析函数),分组排序之后通过每个组中的顺序号来进⾏记录筛选。

SELECT AA.*
FROM YANGGBS AA
INNER JOIN (
SELECT NAME, ROW_NUMBER(PARTITION BY NAME ORDER BY AGE) AS RN
FROM YANGGBS
) BB
ON = AND BB.RN =1
更多的,这种⽅式在分页的实现上⽤途很⼤(通过RN进⾏顺序结果集筛选),⼏乎是数据库层⾯分页最好的解决⽅案。

"抛硬币来决定吧,碎了我们就在⼀起。

"。

SQL中的查询排序

SQL中的查询排序

SQL中的查询排序⼀、SQL基础查询1、select语句格式:select字段from表名;2、where ⽤于限制查询的结果3、查询条件> < >= <= = !=4、与或(AND,OR)5、在不在(IN,NOT IN)6、在[a,b] (between val1 and val2)7、空⾮空(NULL,NOT NULL)8、全部任⼀(ALL,ANY)不能单独使⽤,必须与关系运算符配合9、排重DISTINCT⽤在字段之前⼆、排序1、使⽤ ORDER BY 语句格式:select 字段 from 表名 where 条件 ORDER BY 字段;2、设置升序降序(ASC,DESC)格式:select 字段 from 表名 where 条件 ORDER BY 字段 ASC|DESC3、多项排序格式:select 字段 from 表名 where 条件 ORDER BY 字段 ASC|DESC,字段ASC|DESC三、聚合函数注意:在使⽤⽐较运算符时NULL为最⼤值,在排序时也会受影响把 select 语句的查询结果汇聚成⼀个结果,这样的函数叫聚合函数1、MAX\MIN获取最⼤值和最⼩值,可以是任何数据类型,但只能获取⼀个字段2、AVG\SUM获取平均值、总和nvl(salary,0)3、COUNT统计记录的数量四、分组1、GROUP BY格式:select 组函数 from 表 group by 字段2、HAVING 组判断条件它的真假决定⼀组数据是否返回五、查询语句的执⾏顺序1、格式:select sum(salary) from 表名 where bool order by group by a、from 表名,先确定数据的来源 b、where 确定表中的哪些数据有效 c、group by 字段名,确定分组的依据 d、having 确定组数据是否返回 e、order by 对组数据进⾏排序六、关联查询1、多表查询select 字段 from 表1,表2 where;2、多表查询时有相同字段怎么办 1、表名.字段名 2、表名如果太长,可以给表起别名(from 表别名)3、笛卡尔积 a、8条数据 b、9条数据在多表查询时,⼀定要设置where 条件,否则将得到笛卡尔积七、连接查询当使⽤多表进⾏关联查询时,根据设置的条件会得到不同的结果1、内连接查询:左右两边能匹配上的select last_name ,name from s_emp,s_dept where dept_id=s_dept.id2、外连接:左右两边不能匹配的数据select last_name ,name from s_emp left|right|full outer join s_dept on dept_id=s_dept.id 3、左外连接匹配成功的数据+左表不能匹配的数据4、右外连接匹配成功的数据+右表不能匹配的数据5、全外连接匹配成功的数据+左右表不能匹配的数据。

SQL Server 动态行转列(参数化表名、分组列、行转列字段、字段值)

SQL Server 动态行转列(参数化表名、分组列、行转列字段、字段值)

一.本文所涉及的内容(Contents)本文所涉及的内容(Contents)背景(Contexts)实现代码(SQL Codes)方法一:使用拼接SQL,静态列字段;方法二:使用拼接SQL,动态列字段;方法三:使用PIVOT关系运算符,静态列字段;方法四:使用PIVOT关系运算符,动态列字段;扩展阅读一:参数化表名、分组列、行转列字段、字段值;扩展阅读二:在前面的基础上加入条件过滤;二.背景(Contexts)其实行转列并不是一个什么新鲜的话题了,甚至已经被大家说到烂了,网上的很多例子多多少少都有些问题,所以我希望能让大家快速的看到执行的效果,所以在动态列的基础上再把表、分组字段、行转列字段、值这四个行转列固定需要的值变成真正意义的参数化,大家只需要根据自己的环境,设置参数值,马上就能看到效果了。

行转列的效果图如图1所示:(图1:行转列效果图)(一) 首先我们先创建一个测试表,往里面插入测试数据,返回表记录如图2所示:--创建测试表IF EXISTS (SELECT*FROM sys.objects WHERE object_id=OBJECT_ID(N'[dbo].[TestRows2Columns]') AND type in (N'U'))DROP TABLE[dbo].[TestRows2Columns]GOCREATE TABLE[dbo].[TestRows2Columns]([Id][int]IDENTITY(1,1) NOT NULL,[UserName][nvarchar](50) NULL,[Subject][nvarchar](50) NULL,[Source][numeric](18, 0) NULL) ON[PRIMARY]GO--插入测试数据INSERT INTO[TestRows2Columns] ([UserName],[Subject],[Source])SELECT N'张三',N'语文',60UNION ALLSELECT N'李四',N'数学',70UNION ALLSELECT N'王五',N'英语',80UNION ALLSELECT N'王五',N'数学',75UNION ALLSELECT N'王五',N'语文',57UNION ALLSELECT N'李四',N'语文',80UNION ALLSELECT N'张三',N'英语',100GOSELECT*FROM[TestRows2Columns](图2:样本数据)(二) 先以静态的方式实现行转列,效果如图3所示:--1:静态拼接行转列SELECT[UserName],SUM(CASE[Subject]WHEN'数学'THEN[Source]ELSE0END) AS'[数学]',SUM(CASE[Subject]WHEN'英语'THEN[Source]ELSE0END) AS'[英语]',SUM(CASE[Subject]WHEN'语文'THEN[Source]ELSE0END) AS'[语文]'FROM[TestRows2Columns]GROUP BY[UserName]GO(图3:样本数据)(三) 接着以动态的方式实现行转列,这是使用拼接SQL的方式实现的,所以它适用于SQL Server 2000以上的数据库版本,执行脚本返回的结果如图2所示;--2:动态拼接行转列DECLARE@sql VARCHAR(8000)SET@sql='SELECT [UserName],'SELECT@sql=@sql+'SUM(CASE [Subject] WHEN '''+[Subject]+''' THEN [Source] ELSE 0 END) AS '''+QUOTENAME([Subject])+''','FROM (SELECT DISTINCT[Subject]FROM[TestRows2Columns]) AS aSELECT@sql=LEFT(@sql,LEN(@sql)-1) +' FROM [TestRows2Columns] GROUP BY [UserName]'PRINT(@sql)EXEC(@sql)GO(四) 在SQL Server 2005之后有了一个专门的PIVOT 和UNPIVOT 关系运算符做行列之间的转换,下面是静态的方式实现的,实现效果如图4所示:--3:静态PIVOT行转列SELECT*FROM ( SELECT[UserName] ,[Subject] ,[Source]FROM[TestRows2Columns]) p PIVOT( SUM([Source]) FOR[Subject]IN ( [数学],[英语],[语文] ) ) AS pvtORDER BY pvt.[UserName];GO(图4)(五) 把上面静态的SQL基础上进行修改,这样就不用理会记录里面存储了什么,需要转成什么列名的问题了,脚本如下,效果如图4所示:--4:动态PIVOT行转列DECLARE@sql_str VARCHAR(8000)DECLARE@sql_col VARCHAR(8000)SELECT@sql_col=ISNULL(@sql_col+',','') +QUOTENAME([Subject]) FROM[TestRows2Columns]GROUP BY[Subject]SET@sql_str='SELECT * FROM (SELECT [UserName],[Subject],[Source] FROM [TestRows2Columns]) p PIVOT(SUM([Source]) FOR [Subject] IN ( '+@sql_col+') ) AS pvtORDER BY pvt.[UserName]'PRINT (@sql_str)EXEC (@sql_str)(六) 也许很多人到了上面一步就够了,但是你会发现,当别人拿到你的代码,需要不断的修改成他自己环境中表名、分组列、行转列字段、字段值这几个参数,逻辑如图5所示,所以,我继续对上面的脚本进行修改,你只要设置自己的参数就可以实现行转列了,效果如图4所示:--5:参数化动态PIVOT行转列-- =============================================-- Author: <听风吹雨>-- Create date: <2014.05.26>-- Description: <参数化动态PIVOT行转列>-- Blog: <:///gaizai/>-- =============================================DECLARE@sql_str NVARCHAR(MAX)DECLARE@sql_col NVARCHAR(MAX)DECLARE@tableName SYSNAME --行转列表DECLARE@groupColumn SYSNAME --分组字段DECLARE@row2column SYSNAME --行变列的字段DECLARE@row2columnValue SYSNAME --行变列值的字段SET@tableName='TestRows2Columns'SET@groupColumn='UserName'SET@row2column='Subject'SET@row2columnValue='Source'--从行数据中获取可能存在的列SET@sql_str= N'SELECT @sql_col_out = ISNULL(@sql_col_out + '','','''') + QUOTENAME(['+@row2column+'])FROM ['+@tableName+'] GROUP BY ['+@row2column+']'--PRINT @sql_strEXEC sp_executesql @sql_str,N'@sql_col_out NVARCHAR(MAX) OUTPUT',@sql_col_out=@sql_col OUTPUT --PRINT @sql_colSET@sql_str= N'SELECT * FROM (SELECT ['+@groupColumn+'],['+@row2column+'],['+@row2columnValue+'] FROM ['+@tableName+']) p PIVOT(SUM(['+@row2columnValue+']) FOR ['+@row2column+'] IN ( '+@sql_col+') ) AS pvt ORDER BY pvt.['+@groupColumn+']'--PRINT (@sql_str)EXEC (@sql_str)(图5)(七) 在实际的运用中,我经常遇到需要对基础表的数据进行筛选后再进行行转列,那么下面的脚本将满足你这个需求,效果如图6所示:--6:带条件查询的参数化动态PIVOT行转列-- =============================================-- Author: <听风吹雨>-- Create date: <2014.05.26>-- Description: <参数化动态PIVOT行转列,带条件查询的参数化动态PIVOT行转列>-- Blog: <:///gaizai/>-- =============================================DECLARE@sql_str NVARCHAR(MAX)DECLARE@sql_col NVARCHAR(MAX)DECLARE@sql_where NVARCHAR(MAX)DECLARE@tableName SYSNAME --行转列表DECLARE@groupColumn SYSNAME --分组字段DECLARE@row2column SYSNAME --行变列的字段DECLARE@row2columnValue SYSNAME --行变列值的字段SET@tableName='TestRows2Columns'SET@groupColumn='UserName'SET@row2column='Subject'SET@row2columnValue='Source'SET@sql_where='WHERE UserName = ''王五'''--从行数据中获取可能存在的列SET@sql_str= N'SELECT @sql_col_out = ISNULL(@sql_col_out + '','','''') + QUOTENAME(['+@row2column+'])FROM ['+@tableName+'] '+@sql_where+' GROUP BY ['+@row2column+']'--PRINT @sql_strEXEC sp_executesql @sql_str,N'@sql_col_out NVARCHAR(MAX) OUTPUT',@sql_col_out=@sql_col OUTPUT --PRINT @sql_colSET@sql_str= N'SELECT * FROM (SELECT ['+@groupColumn+'],['+@row2column+'],['+@row2columnValue+'] FROM['+@tableName+']'+@sql_where+') p PIVOT(SUM(['+@row2columnValue+']) FOR ['+@row2column+'] IN ( '+@sql_col+') ) AS pvt ORDER BY pvt.['+@groupColumn+']'--PRINT (@sql_str)EXEC (@sql_str)(图6)。

SQL分组排序后取每组最新一条数据的另一种思路

SQL分组排序后取每组最新一条数据的另一种思路

SQL分组排序后取每组最新⼀条数据的另⼀种思路在hibernate框架和mysql、oracle两种数据库兼容的项⽬中实现查询每个id最新更新的⼀条数据。

之前⼯作中⼀直⽤的mybatis+oracle数据库这种,⼀般写这类分组排序取每组最新⼀条数据的sql都是使⽤row_number() over()函数来实现例如:select t1.* from ( select t.*, ROW_NUMBER() over(partition t.id order by t.update_time desc) as rn from table_name t) t1 where t1.rn = 1;但是新公司项⽬是兼容mysql和oracle两种数据库切换的,那么row_number() over()在使⽤mysql的情况下会出现错误,所以我在⽹上查找了⼀下mysql实现分组排序取最新数据的例⼦有两种写法,如下:第⼀种select t1.*from table_name t1, (select t.id, max(t.update_time) as uTime from table_name t group by t.id) t2where 1=1and t1.id = t2.idand t1.update_time = t2.uTime;第⼆种(这⾥limit是为了固定⼦查询中的排序,如果没有这个limit,外层使⽤虚拟表t1进⾏group by的时候就不会根据之前update_time排好的倒序进⾏分组了。

limit具体的数字可以根据要查询数据的总数来决定。

)select t1.* from ( select * from table_name t order by t.update_time desc limit 1000) t1 group by t1.id;这⾥⼜遇到了⼀个问题,虽然第⼀种⽅式使⽤mysql和oracle都可以查询,但是hibernate是不⽀持from (⼦查询) ... 这种结构的sql的,因为hibernate的核⼼是⾯向对象⽽⾮⾯向数据库,⽹上搜到是这种解决⽅案解决hibernate不⽀持from (⼦查询) ... 参考地址:为了⼀个⼦查询再新建⼀个实体类...虽然觉得这样有点⿇烦但是我还是搜索了⼀下整个项⽬看有没有类似的做法,结果⼀个都没有找到!这时候我请教了⼀下部门的⽼⼈想看看他们做这类查询是如何处理的,⼤佬给出的⽅案是换⼀种sql写法如下:select * from table_name t1 where t1.update_time= (select max(t.update_time) from table_name t where t.id= t1.id);⾄此问题解决...。

sql 分组条件

sql 分组条件

sql 分组条件SQL分组是一种常用的数据处理方法,可以根据指定的条件对数据进行分组并进行聚合计算。

下面将介绍几种常见的SQL分组条件及其用法。

一、按照单个字段分组最常见的分组条件就是按照单个字段进行分组。

比如我们有一个订单表,其中包含了订单号、客户姓名、订单金额等字段。

现在我们希望按照客户姓名对订单进行分组,统计每个客户的订单总金额。

可以使用以下SQL语句实现:```SELECT 客户姓名, SUM(订单金额) AS 订单总金额FROM 订单表GROUP BY 客户姓名;```通过使用GROUP BY子句加上聚合函数SUM,可以按照客户姓名分组并计算每个客户的订单总金额。

二、按照多个字段分组除了按照单个字段进行分组外,我们还可以按照多个字段进行分组。

比如我们希望按照客户姓名和订单日期对订单进行分组,统计每个客户每天的订单总金额。

可以使用以下SQL语句实现:```SELECT 客户姓名, 订单日期, SUM(订单金额) AS 订单总金额FROM 订单表GROUP BY 客户姓名, 订单日期;```通过在GROUP BY子句中指定多个字段,可以按照客户姓名和订单日期进行分组,并计算每个分组的订单总金额。

三、按照条件分组除了按照字段进行分组外,我们还可以根据条件进行分组。

比如我们希望按照订单金额的大小对订单进行分组,统计每个分组的订单数量。

可以使用以下SQL语句实现:```SELECT CASEWHEN 订单金额 < 1000 THEN '小额订单'WHEN 订单金额 >= 1000 AND 订单金额 < 5000 THEN '中额订单'ELSE '大额订单'END AS 订单类别,COUNT(*) AS 订单数量FROM 订单表GROUP BY CASEWHEN 订单金额 < 1000 THEN '小额订单'WHEN 订单金额 >= 1000 AND 订单金额 < 5000 THEN '中额订单'ELSE '大额订单'END;```通过使用CASE语句将订单金额分为不同的类别,然后按照订单类别进行分组,并计算每个分组的订单数量。

SQL技巧-分组排序,取最新数据的两种方法

SQL技巧-分组排序,取最新数据的两种方法

SQL技巧-分组排序,取最新数据的两种⽅法写SQL的时候 , 如果要分组取最新的数据 , ⼀般可以有两种⽅法1drop table if exists #a23select*into #a from (4select symbol='001',price=10,tdate='20190601'5union all6select symbol='001',price=15,tdate='20190801'7union all8select symbol='002',price=20,tdate='20190601'9union all10select symbol='002',price=25,tdate='20190801'11 )a order by tdate1213select*from #a -- 查看表中数据14-- 常规写法15select*from #a x16where tdate=(select max(tdate) from #a where x.symbol=symbol)1718-- 等价写法19select symbol,price,tdate from (20select symbol,price,tdate,rn=row_number() over(partition by symbol order by tdate desc) from #a21 )a where rn=12223drop table #a结果如下图前提是⽇期字段 tdate不会有重复1.第⼀种是⽤⼦查询max , 这种⽅法常⽤⽽且简单但是有局限性就是只能对⼀个字段进⾏排序 , 分组条件即where 后⾯的条件 这⾥是symbol 还可以加上其他的条件⽐如 x.symbol=symbol and x.exchange=exchange 这⾥的条件和分组条件group by以及row_number()的partition by条件实现的功能是⼀样的 注意#a的表的别名 x 是写在哪⾥的不能写在⼦查询⾥⾯ 如果写在⼦查询⾥⾯那么where x.symbol=symbol就等于没写相当于取整张表的max(tdate) 没有实现分组作⽤ 但是刚开始写SQL的时候会难以理解为啥这样也可以2.另⼀种是row_number() 这种⽅法如果是只⽤在取最新数据 , 就有点⼤材⼩⽤了⽽且不如上⼀种⽅法简单但是他可以在order by tdate 排序之后增加其他的排序规则⽐如 order by tdate desc,price desc但这个例⼦后⾯再写其他的排序字段也没⽤了因为tdate是唯⼀的谢谢!。

sql分组用法

sql分组用法

sql分组用法
SQL中的分组用法是指利用GROUPBY子句对查询结果进行分组的操作。

通过分组操作,可以将查询结果按照指定的列或表达式进行分组,并对每个组计算聚合函数的值,如SUM、AVG、COUNT等。

在使用GROUP BY子句时,需要注意以下几点:
1.只有在SELECT语句中使用的列,才可以在GROUP BY子句中使用。

2.GROUP BY子句中可以包含多个列名或表达式,用逗号隔开。

3.GROUP BY子句中的列名或表达式,必须按照SELECT语句中的顺序列出。

4.如果SELECT语句中使用了聚合函数,则除了包含在GROUP BY 子句中的列外,其他列必须使用聚合函数进行计算。

例如,下面的SQL语句查询订单表中每个用户的订单总金额:
SELECT user_id, SUM(amount)
FROM orders
GROUP BY user_id;
在该查询中,使用了GROUP BY子句将订单表按照user_id分组,并使用SUM函数计算每个用户的订单总金额。

总之,SQL中的分组用法可以帮助我们对查询结果进行分组统计,方便我们获取有用的信息。

- 1 -。

SQL server常用函数

SQL server常用函数

一、.修改查询出来的字段属性①、cast 和convert都是用来将一种数据类型的表达式转换为另一种数据类型的表达式cast一般更容易使用,convert的优点是可以格式化日期和数值.⑴、cast()语句语句形式为:select cast(字段as int) as 自定义字段名from table1查询table1的字段内容并且将数据类型转换为int类型显现出来,重新附一个别名⑵、Convert() 语句⑴语句形式为:select convert(int,字段) as 自定义字段名from table2查询table1的字段内容并且将数据类型转换为int类型显现出来,重新附一个别名⑵语句形式为:select convert(char(10),getdate(),102)获取当前日期,并且格式为yy.mm.dd(最多占10个字节)第三参数如下:日期类型格式10003 19 20084:45PM10103/19/20081022008.03.1910319/03/200810419.03.200810519-03-200810619 03 200810703 19, 200810816:45:0010903 19 20084:45:00:11003-19-20081112008/03/191122008031911319 03 2008 16:45:00:11416:45:00:000②、str()函数--数值转换字符类型函数格式:str(参数1(必填),参数2(选填),参数3(选填))参数1 数值字段,参数2 指定的总长度(包括逗号,小数,整数与空,默认为10),参数3 保留的小数位数转换规则:先看整数部分是否满足转换长度,只要长度值小于整数长度就返回“*”;若长度值大于整数长度,再看小数部分。

小数部分能按要求转换后仍不足转换长度,再在左侧补空格二、对小数值进行取值①、round() 函数--遵循四舍五入保留指定的小数位函数格式:round(参数1,参数2)参数1:数值。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

declare @班级表table
(
班级编号int,
班级名称nvarchar(50)
)
insert into @班级表(班级编号,班级名称)
select 1,'三年级一班 3-1'
union all
select 2,'三年级二班 3-2'
union all
select 3,'三年级三班 3-3'
declare @成绩表table
(
学生编号int,
班级编号int,
学生姓名nvarchar(50),
语文numeric(18,1),
数学numeric(18,1)
)
insert into @成绩表(学生编号,班级编号,学生姓名,语文,数学)
select 1,1,'3-1 A同学',85,91
union all
select 2,1,'3-1 B同学',93,96
union all
select 3,1,'3-1 C同学',87,81
union all
select 4,2,'3-2 A同学',87,82
union all
select 5,2,'3-2 B同学',79,84
union all
select 6,3,'3-3 A同学',93,95
union all
select 7,3,'3-3 B同学',93,95
union all
select 8,3,'3-3 C同学',93,95
--取每个班语文第一相同成绩并列
select*from (
select RANK()OVER(PARTITION BY b.班级编号ORDER BY b.语文DESC) Px,b.*,a.班级名称
from @班级表as a inner join @成绩表as b on a.班级编号=b.班级编号
)as tbc where Px=1
order by班级编号
select*from @成绩表as a inner join @班级表as b on a.班级编号=b.班级编号order by b.班级编号。

相关文档
最新文档