我正在尝试编写一个sql查询,对于每个返回的行,也会根据其行位置返回一个百分比(0-100)。为了进一步复杂化,查询目前也已分组。以下是一些可以使用的示例数据:
create table #test(StockId int)
insert into #test values (101), (101), (202), (202), (303), (404), (505)
select
StockId,
count(*) as BinMovements
from #test
group by StockId
order by BinMovements desc
此查询当前返回:
StockId,BinMovements
101,2 202,2 303,1 404,1 505,1
(虽然很明显,因为BinMovements是2或1,所以以不同的顺序返回StockIds同样正确):
202,2
101,2 404,1 303,1 505,1
我想添加一个'百分比'列,但这实际上只是基于行位置,所以我希望看到以下值:
101,2,11
202,2,80 303,1,61 404,1,40 505,1,20
我想解决方案可能涉及ROW_NUMBER
,我开始沿着这条路走下去,以为我可以得到ROW_NUMBER /总行数* 100,但由于某些原因这不起作用。可能是因为group by子句?
select
StockId,
count(*) as BinMovements,
ROW_NUMBER() OVER(order by (count(*))) as RowNumber,
count(*) over () as TotalCount,
(ROW_NUMBER() OVER(order by (count(*)))) / (count(*) over ()) * 100 as Percentage
from #test
group by StockId
order by RowNumber desc
返回:
StockId BinMovements RowNumber TotalCount Percentage
202 2 5 5 100
101 2 4 5 0
505 1 3 5 0
404 1 2 5 0
303 1 1 5 0
如果可能的话,我宁愿在单个选择中执行此操作,但如果不将其包装在外部选择中可能是一种解决方案。感谢
答案 0 :(得分:1)
COUNT和ROW_NUMBER函数都返回BIGINT。 因此除法的结果也转换为BIGINT。
这有效(你应该在分裂之前相乘):
(ROW_NUMBER() OVER(order by (count(*)))) * 100 / (count(*) over ()) as Percentage
答案 1 :(得分:1)
使用类似于您问题的count() over()
和row_number()
,只需重新排序等式。
请注意,order by
的{{1}}与语句的row_number()
相反,因为我们希望将百分比设置为100.否则您最终可以将80作为第一行,100作为第二行,等等。
order by
rextester演示:http://rextester.com/TCPE10348
select
StockId
, BinMovements = count(*)
, Percentage = 100/count(*) over ()
* row_number() over (order by count(*) asc, stockid desc)
from #test
group by StockId
order by BinMovements desc, StockId asc
如果您想要小数百分比,请在等式中将+---------+--------------+------------+
| StockId | BinMovements | Percentage |
+---------+--------------+------------+
| 101 | 2 | 100 |
| 202 | 2 | 80 |
| 303 | 1 | 60 |
| 404 | 1 | 40 |
| 505 | 1 | 20 |
+---------+--------------+------------+
更改为100
。