首页 新闻 会员 周边

关于SQL中一个group by语句怎么写

0
悬赏园豆:10 [已解决问题] 解决于 2009-11-08 11:02

               问题是这样的,假如公司有10000人,公司的员工的薪水从500到10000不等,现在要以500为一个梯度,统计每个阶段的员工的人数

结果格式:

     工资水平                  人数

500~999                        10
1000~1499                    324

1500~2000                    459

.....                                ...

9500~10000                    33

 

 

     我是初学者,希望能够讲的详细点。谢谢!

问题补充: 能够用MSSQL 的 语句写一个吗??
小老鼠的博客的主页 小老鼠的博客 | 初学一级 | 园豆:25
提问于:2009-11-07 18:31
< >
分享
最佳答案
0

楼上的周强其实已经给出了解答的本质,跟着本质去写SQL语句是件很简单的问题,楼主应该多动动脑筋,同时多动动手,我给出自己在MS-SQL2000(注意产品的特定环境,其他数据库产品实现方式或许略有不同)下的完整模拟过程吧,就当我犯错误坑害“小老鼠”。

建表,插入相应测试数据
USE D_Salary
GO

CREATE TABLE T_EmpSalary
(
AutoID
int IDENTITY(1,1) PRIMARY KEY,
EmpName
nvarchar(20) NOT NULL,
Salary
int NOT NULL
)
GO


USE D_Salary
GO
DECLARE @Index int,
@EmpName nvarchar(20),
@Salary int
SET @Index = 1;
SET @EmpName = 'rainnoless';
SET @Salary = 500;

WHILE @Index < 10001
BEGIN
INSERT INTO [D_Salary].[dbo].[T_EmpSalary]
(EmpName, Salary)
VALUES
(
@EmpName, @Salary)

IF @@ERROR = 0
BEGIN
IF @Index BETWEEN 1 AND 9000
SET @Salary = 500 + @Index
ELSE
SET @Salary = @Index

SET @Index = @Index + 1;
SET @EmpName = 'rainnoless' + CAST(@Index AS VARCHAR(5));

CONTINUE
END
ELSE
BREAK
END

 

测试数据入库后,请自行将大小连续的数据做一些修改,否则出来的统计数据都是500……。

在真实的生产环境,对表建立相应索引是必须的,这里就不做复述了,因为如果建立索引这个不是一两句话能说清楚,需要自己去实践摸索吧。

最后给出你要的答案,利用一个派生表的查询,得到你需要的效果集:

SELECT ( CAST(MIN(minSalary) AS VARCHAR(5)) + '~' + CAST(MAX(maxSalary) AS VARCHAR(5)) ) AS SalaryBound, COUNT(Totals) AS Totals
FROM (SELECT MAX(Salary/500) AS Totals, MAX(Salary) AS maxSalary, MIN(Salary) AS minSalary
FROM [D_Salary].[dbo].[T_EmpSalary]
GROUP BY AutoID) AS SalaryTotals
GROUP BY Totals
ORDER BY MIN(minSalary)


在涉及到计算列的时候,我想把其中的派生表单独拿出来作为一个视图:

CREATE VIEW V_SalaryTotals
AS
SELECT MAX(Salary/500) AS Totals, MAX(Salary) AS maxSalary, MIN(Salary) AS minSalary
FROM [D_Salary].[dbo].[T_EmpSalary]
GROUP BY AutoID
GO

如果有必要在数据量特别大的时候,可以建立视图索引,来提高查询的效率,最终的查询SQL语句变成:
SELECT ( CAST(MIN(minSalary) AS VARCHAR(5)) + '~' + CAST(MAX(maxSalary) AS VARCHAR(5)) ) AS SalaryBound, COUNT(Totals) AS Totals
FROM [D_Salary].[dbo].[V_SalaryTotals]
GROUP BY Totals
ORDER BY MIN(minSalary)

最后查询的结果集如图:
查询结果集
图文并茂,不知道最后能否满足小老鼠的要求?最后希望你能有所收获,动手把我的测试代码敲打敲打,呵呵。
收获园豆:8
rainnoless | 小虾三级 |园豆:613 | 2009-11-08 01:42
谢谢你,rainnoless,你的答案很详细,是我受益匪浅啊,我会努力的!!
小老鼠的博客 | 园豆:25 (初学一级) | 2009-11-08 11:01
呵呵,能有获益就好,不客气。
rainnoless | 园豆:613 (小虾三级) | 2009-11-08 11:33
其他回答(3)
0

给你一个ORACLE的写法

思路是一样的.

select count(1),(a*500)||'-'||( (a+1)*500-1) step from(
select id,salary, trunc(SALARY/500)  a From woody

) group by a


收获园豆:1
woody.wu | 园豆:3621 (老鸟四级) | 2009-11-07 21:30
看不懂 ,不过还是很谢谢你!
支持(0) 反对(0) 小老鼠的博客 | 园豆:25 (初学一级) | 2009-11-07 22:02
0

很简单嘛,用工资/500  会得出0-20之间的整数,然后每个整数有多少个就可以了,然后这个整数*500就是工资区间。

收获园豆:1
周强 | 园豆:266 (菜鸟二级) | 2009-11-07 21:37
能够讲再的详细点吗?
支持(0) 反对(0) 小老鼠的博客 | 园豆:25 (初学一级) | 2009-11-07 22:02
0

declare @i int,@sql varchar(500)
select @i=0,@sql='select ''0~500'' as 工资水平,count(*) as 人数 from 员工薪水表 where 薪水 between 0 and 500'
set @i=500
while @i<10000
begin
set @sql=@sql+' Union select '''+CAST(@i as varchar)+'~'+CAST(@i+500 as varchar)+''', count(*) from 员工薪水表 where 薪水 between '+cast(@i as varchar)+' and '+cast(@i+500 as varchar)
set @i=@i+500
end

exec(@sql)

我这个简单些,拼接一个字符串就行了。

dege301 | 园豆:2825 (老鸟四级) | 2009-11-08 01:50
你有才,这种拼接到先得更复杂,不符合一般逻辑啊,呵呵。
支持(0) 反对(0) rainnoless | 园豆:613 (小虾三级) | 2009-11-08 01:57
复杂从何谈起,思路很简单,要是只找0-500的人数一个语句就出来了,现在不就把几个分段的结果Union起来吗? 不符合一般逻辑倒是有点,因为在拼接的时候很容易出错,大家都不太赞成用。
支持(0) 反对(0) dege301 | 园豆:2825 (老鸟四级) | 2009-11-08 12:07
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册