MSSQL Group by Percentage

时间:2016-03-26 11:23:58

标签: mysql sql-server

我试图找到一种方法将我的结果分组为3组,预定义为0-33%,34-66%和67-100%。计算已被设置为“耗尽”。我想将此列的顶部,中间和底部分组为三个不同的组。这是我在多个表中使用的查询。

我假设我需要首先在SELECT中找到最高值,以便我可以计算百分比,但我似乎无法找到一种方法来做到这一点。从那里我不知道如何根据百分比对项目进行分组。

SELECT     l.name AS Location, i.name AS ItemName, li.par, COUNT(*) AS Sales, li.par - COUNT(*) AS Depletion
FROM         shoppingcartdetail AS o INNER JOIN
                  item AS i ON i.id = o.itemid INNER JOIN
                  location AS l ON o.locationid = l.id INNER JOIN
                  location_item AS li ON i.id = li.itemid
WHERE     (CONVERT(datetime, o.created_date_time, 101) BETWEEN GETDATE() - l.service_interval AND GETDATE()) AND (o.locationid = 1)
GROUP BY i.barcode, i.name, l.name, li.par

示例结果

ItemName                 | avgshelflife | unitcost | par | Sales | Depletion
Dr. Pepper Bottle 20 oz  | 90           | 0.83     | 70  | 31    | 39
Mountain Dew Bottle 20 oz| NULL         |NULL      | 70  | 27    | 43
Coke Can 12 oz           | NULL         |NULL      | 30  | 22    | 8
M&M's Peanut 1.74 oz     | 90           | 0.60     | 66  | 14    | 52
Dr. Pepper Can 12 oz     | 180          | 0.38     | 30  | 13    | 17

M& M的花生1.74盎司将达到最高耗尽率为50%的100%阈值。项目将分为三组,并添加新列。

在这种情况下:Y =%* 52(M& M花生耗尽1.74盎司)

Group0-30% is 0-17
Group31-66% is 18-34
Group66-100% is 35-52

结果

Group0-30% Coke Can 12 oz   
Group31-66% Dr. Pepper Can 12 oz
Group66-100% Dr. Pepper Bottle 20 oz, Mountain Dew Bottle 20 oz, M&M's Peanut 1.74 oz

提前致谢!

3 个答案:

答案 0 :(得分:1)

据我了解你的问题,你想要显示“耗尽”,这是你需要在组中显示的百分比。如果是这样你就可以这样使用。

select *,CASE 
    WHEN (Depletion < 34) THEN 
        'Group0-30%' + ItemName 
    ELSE 
        CASE 
            WHEN (Depletion < 67) THEN 
                'Group31-66%' + ItemName 
            ELSE 
                'Group66-100%' + ItemName 
        END
    END from (
        SELECT     l.name AS Location, i.name AS ItemName, li.par, COUNT(*) AS Sales, li.par - COUNT(*) AS Depletion
        FROM         shoppingcartdetail AS o INNER JOIN
                          item AS i ON i.id = o.itemid INNER JOIN
                          location AS l ON o.locationid = l.id INNER JOIN
                          location_item AS li ON i.id = li.itemid
        WHERE     (CONVERT(datetime, o.created_date_time, 101) BETWEEN GETDATE() - l.service_interval AND GETDATE()) AND (o.locationid = 1)
        GROUP BY i.barcode, i.name, l.name, li.par) t

如果不是那样的话,请提供数据以便更好地理解。

谢谢,

答案 1 :(得分:0)

这可行(虽然丑陋),想法是使用百分之高,然后做其余的,我使用sales.orders表进行演示,但这个想法保持不变..

step1:将所有百分比分成三个临时表,由于标识col和laziness,我使用了三个不同的临时表,你可以用一个

select top 33 percent * ,'37 pcnt' as 'pcnt'  into #temp1 from sales.orders order by orderdate desc

select top 67percent * ,'67 pcnt' as 'pcnt'  into #temp2 from sales.orders order by orderdate desc

select  * ,'100 pcnt' as 'pcnt'  into #temp3 from sales.orders 

现在下一步是我们获取数据的地方..

with cte
as
(
select * from #temp
union all
select * from
(
select * from #temp1 t1 where not exists(select 1 from #temp t2 where t2.orderid=t1.orderid) 
)c

)
select * from cte
union all
select * from
(
select * from #temp3 t3 where not exists(select 1 from cte where cte.orderid=t3.orderid)
)b

输出:  enter image description here

答案 2 :(得分:0)

您还可以声明一个根据行号计算百分比的函数。下面是逻辑,您可能需要根据需要进行优化。另外需要注意的是,某些行可能会说零百分比,但返回的行符合最高百分比条款..

在我的演示中,Orderid是一个PK,您可以在它的情况下将其更改为唯一编号或PK

Alter function dbo.getpercent
(@orderid as int
)
returns int
as
begin

declare @pcnt int
;with cte
as
(
select row_number() over (order by orderid)  as rn,orderid
from sales.orders)
select @pcnt=(cast(rn as float)/830)*100 from cte 
where orderid=@orderid

return @pcnt
end

select dbo.getpercent(orderid) ,* from sales.orders
order by orderid