【问题标题】:Ranking Customers SQL Server Script客户排名 SQL Server 脚本
【发布时间】:2019-03-12 17:56:15
【问题描述】:

需要一点帮助:


正在编辑:我正在尝试根据销售额确定谁是我的前 40% 客户。然后,去掉那些客户,给我前 30%。然后删除这两个数据集,它们现在是 mytop 20%,等等


这是场景:。假设我们的总销售额为 1,000,000 美元。我想要一个客户排名系统来对 A、B、C 和 D 客户进行排名,看看谁是我最好的客户。

“A”类客户的交易占总收入的 40% --- 40 万美元 “B”客户交易接下来的 30% --- $300k “C”客户交易接下来的 20% --- $200k “D”客户交易总收入的最后 10%——10 万美元

这是我的 SQL:

declare @TotalTotal decimal(18,2)
declare @ATotalRankTotal decimal(18,2)
declare @BTotalRankTotal decimal(18,2)
declare @CTotalRankTotal decimal(18,2)
declare @DTotalRankTotal decimal(18,2)

SET @TotalTotal = 1000000

set @ATotalRankTotal = @TotalTotal * .40
set @BTotalRankTotal = @ATotalRankTotal + (@TotalTotal * .30)
set @CTotalRankTotal = @BTotalRankTotal + (@TotalTotal * .20)
set @DTotalRankTotal = @CTotalRankTotal + (@TotalTotal * .10)

select
        CustomerName
        , sum(TotalSales)
        , TotalCustomerRank = CASE
            WHEN SUM(sum(TotalSales)) over (order by SUM(TotalSales) desc) <= @ATotalRankTotal then
                'A'
            WHEN SUM(sum(TotalSales)) over (order by SUM(TotalSales) desc) > @ATotalRankTotal and SUM(sum(TotalSales)) over (order by SUM(TotalSales) desc) <= @BTotalRankTotal then
                'B'
            WHEN SUM(sum(TotalSales)) over (order by SUM(TotalSales) desc) > @BTotalRankTotal and SUM(sum(TotalSales)) over (order by SUM(TotalSales) desc) <= @CTotalRankTotal then
                'C'
            else
                'D'
            end
    from 
        Customers
    GROUP BY 
        CustomerName

我想出的问题是,我可能没有一个销售额达到 40 万美元或更多的客户,所以我永远不会知道我的“A”客户是谁。

关于如何编写脚本以确定哪些客户占据了我的前 40% 的收入(我的“A”客户),哪些客户占据了接下来的 30%(我的“B”客户),哪些客户占据了任何想法占下一个 20%(我的“C”客户),哪些客户占最后 10%(我的“D”客户)?

【问题讨论】:

  • 我不确定一个样本数据集是否足够,可能需要提供多个场景。我不认为你对你想要的东西有很好的把握。 “哪些客户占据了我前 40% 的收入”并不是一个明确的描述。
  • 只需添加另一列,并过滤每个案例其中 SalesDept = "A" 表示第一种情况,或 = "B" 表示第二种情况,...
  • 我对我正在尝试做的事情有很好的把握,可能只是没有正确解释。根据销售额,我的前 40% 的客户是谁。然后,删除那些客户,现在他们是我的前 30%。然后删除这两个数据集,现在排名前 20%,等等。
  • 正如@GordonLinoff 所说,为您的每个场景提供相关预期结果的样本数据将非常有帮助。
  • 你考虑过使用 RANK() 吗?

标签: sql sql-server tsql


【解决方案1】:

这在 Northwind 上运行得非常快。应该正是你想要的。它专注于前 40% 的销售额,而不是前 40% 的客户数量。

产生以下结果

DECLARE 
    @TotalTotal INT = 0;

DECLARE @st TABLE
(
    CustomerID  nchar(5),
    CustTotal   INT,
    RunningTotal INT,
    RunningPCT   INT,
    CustRank    nchar(1)
);

DECLARE
    @CustomerID  nchar(5),
    @CustTotal   INT,
    @RunningTotal INT = 0,
    @RunningPCT   INT = 0,  
    @CustRank    nchar(1)= ' ';

DECLARE c CURSOR
    LOCAL STATIC FORWARD_ONLY READ_ONLY
    FOR

        SELECT
              oo.CustomerID

              ,SUM( od.[UnitPrice] * od.[Quantity] ) as CustTotal

          FROM [Northwind].[dbo].[Order Details] as od
          left join [Northwind].[dbo].[Orders] as oo
          on od.OrderID = oo.OrderID
          left join [Northwind].[dbo].[Products] as pd
          on od.ProductID = pd.ProductID

          Group by oo.CustomerID
          order by SUM( od.[UnitPrice] * od.[Quantity] ) desc
    ;

-- get the Denominator for the Percent ranking  
OPEN c; 
FETCH NEXT FROM c INTO @CustomerID, @CustTotal;
WHILE @@FETCH_STATUS = 0
BEGIN
    SET @TotalTotal = @TotalTotal + @CustTotal;
    FETCH NEXT FROM c INTO @CustomerID, @CustTotal;
END
CLOSE c;

-- compute Rank for each customer
OPEN c;
FETCH NEXT FROM c INTO @CustomerID, @CustTotal;

WHILE @@FETCH_STATUS = 0
BEGIN
    SET @RunningTotal = @RunningTotal + @CustTotal;
    SET @RunningPCT   =  (@RunningTotal * 100 / @TotalTotal);
    SET @CustRank = Case
        When @RunningPCT <= 40 Then 'A'
        When @RunningPCT <= 70 Then 'B'
        When @RunningPCT <= 90 Then 'C'
        Else 'D' End ;
    INSERT @st(CustomerID, CustTotal,  RunningTotal, RunningPCT, CustRank)
        SELECT @CustomerID,  @CustTotal, @RunningTotal, @RunningPCT, @CustRank;

    FETCH NEXT FROM c INTO @CustomerID, @CustTotal;
END

CLOSE c;
DEALLOCATE c; 

-- Show the results 
Select @TotalTotal;
Select * From @st;

【讨论】:

  • 虽然我试图避免使用游标,但这确实起到了作用。谢谢!
【解决方案2】:

我是按这句话来的:

根据销售额,我的前 40% 的客户是谁。

换句话说,如果您有 10 位客户,则无论他们占总收入的百分比如何,您都希望排名前 4 位。如果这不是您要问的,那么您的问题仍然不够清楚。

您可以使用内置的NTILE 函数来获得它。使用NTILE(10) OVER (ORDER BY Revenue) 将您的客户放入占客户总数 10% 的存储桶中,您可以通过在范围内检查此值来获得 A、B、C、D。

假设您使用上面的 NTILE 函数生成一个名为 MyNtile 的列,那么您可以执行以下操作:

CASE WHEN MyNtile <= 4 THEN 'A'
     WHEN MyNtile BETWEEN 5 AND 7 THEN 'B'
     etc..

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-05
    • 2011-07-17
    • 1970-01-01
    • 2018-09-23
    • 1970-01-01
    • 1970-01-01
    • 2016-08-05
    相关资源
    最近更新 更多