用于对列上的数据进行分区并返回最大值

时间:2016-08-30 18:28:47

标签: sql sql-server tsql sql-server-2014

我需要根据传播目标达到日期来计算奖金支出,如下所示:

Spread Goal | Date Achieved     | Bonus Payout
---------------------------------------------- 
$3,500      | < 27 wks          | $2,000 
$3,500      | 27 wks to 34 wks  | $1,000 
$3,500      | > 34 wks          | $0

我在SQL Server 2014中有一个表,其中数据的子集如下:

EMP_ID   WK_NUM   NET_SPRD_LCL 
123      10       0 
123      11       1500 
123      15       3600 
123      18       3800 
123      19       4000

根据要求,我需要在2 连续 NET_SPRD_LCL期间查找3500大于或等于wk_num的记录。

所以,在我的示例中,WK_NUM 15和18(在我的情况下是连续因为我有一个日历表,我加入以排除假期周< / em>)小于27 wks并且NET_SPRD_LCL > 3500

对于这种情况,我想输出MAX(WK_NUM),它与NET_SPRD_LCLBONUSPAYOUT = 2000相关联。因此,输出应如下:

EMP_ID   WK_NUM   NET_SPRD_LCL   BONUSPAYOUT
123      18       3800           2000

如果符合第一个要求,脚本应输出并退出。如果没有,那么我将寻找Date Achieved介于27 wks to 34 wks之间的第二个要求。

我希望我能够清楚地解释我的要求: - )

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

好问题!我打破了我的想法,像一个回合中的4行3500和更多。想出了这个。

您可以使用CTE,递归CTE和ROW_NUMBER():

;WITH cte AS(
SELECT  EMP_ID, 
        WK_NUM, 
        NET_SPRD_LCL,
        ROW_NUMBER() OVER (PARTITION BY EMP_ID ORDER BY WK_NUM) rn
FROM YourTable
)
, recur AS (
SELECT  EMP_ID,
        WK_NUM, 
        NET_SPRD_LCL,
        rn,
        1 as lev
FROM cte
WHERE rn = 1
UNION ALL
SELECT  c.EMP_ID,
        c.WK_NUM, 
        c.NET_SPRD_LCL,
        c.rn,
        CASE WHEN c.NET_SPRD_LCL < 3500 THEN Lev+1 ELSE Lev END 
FROM cte c
INNER JOIN recur r
    ON r.rn+1 = c.rn
)

SELECT TOP 1 WITH TIES
                    EMP_ID,
                    WK_NUM, 
                    NET_SPRD_LCL,
                    CASE WHEN WK_NUM < 27 THEN $2000
                            WHEN WK_NUM between 27 and 34 THEN $1000
                            ELSE $0 END as Bonus
FROM recur
WHERE NET_SPRD_LCL >= 3500
ORDER BY ROW_NUMBER() OVER(PARTITION BY EMP_ID,lev ORDER BY WK_NUM)%2

您提供的数据的输出:

EMP_ID  WK_NUM  NET_SPRD_LCL    Bonus
123     18      3800            2000,00