简单的 sql over (partition by) 没有按预期工作

Posted

技术标签:

【中文标题】简单的 sql over (partition by) 没有按预期工作【英文标题】:simple sql over (partition by) not working as expected 【发布时间】:2016-09-15 07:58:25 【问题描述】:

感觉应该很简单,但我的大脑一片空白,所以不胜感激!

假设我有这个数据集

Date     sale_id    salesperson Missed_payment_this_month
01/01/2016  1001    John         1
01/01/2016  1002    Bob          0
01/01/2016  1003    Bob          0
01/01/2016  1004    John        N/A
01/02/2016  1001    John         1
01/02/2016  1002    Bob          1
01/02/2016  1003    Bob          0
01/02/2016  1004    John         1
01/03/2016  1001    John         1
01/03/2016  1002    Bob          0
01/03/2016  1003    Bob          0
01/03/2016  1004    John         1    

并想将这两列添加到末尾。他们通过 sales_id 和 salesperson 查看之前错过的付款次数。

Previous_missed_payment_by_sale_id  Previous_missed_payment_by_sales person
    0                                           0
    0                                           0
    0                                           0
    0                                           0
    1                                           1
    0                                           0
    0                                           0
    0                                           1
    2                                           3
    1                                           1
    0                                           1
    1                                           3

sales_id 没问题,但超过销售人员会给我一个错误(分组依据)或添加额外的列。我需要保持行不变。

我最好的猜测是返回额外的列:

 select t1.Date, t1.sale_id, t1.salesperson
 ,sum(case when t2.Missed_payment_this_month = '1' then 1 else 0 end)             previous_missed_sales_id
 ,sum(case when t2.Missed_payment_this_month = '1' then 1 else 0 end) OVER (PARTITION by t1.salesperson) previous_missed_salesperson

 from [dbo].[simple_join_table2] t1
 inner join [dbo].[simple_join_table2] t2 on 
(t2.[Date] < t1.[Date] AND t1.[sale_id] = t2.[sale_id])

 group by t1.Date, t1.sale_id, t1.salesperson
 ,case when t2.Missed_payment_this_month = '1' then 1 else 0 end

这是输出:

Date    sale_id salesperson previous_missed_sales_id    previous_missed_salesperson
01/02/2016  1002    Bob         0                                   1
01/02/2016  1003    Bob         0                                   1
01/03/2016  1002    Bob         0                                   1
01/03/2016  1002    Bob         1                                   1
01/03/2016  1003    Bob         0                                   1
01/02/2016  1001    John        1                                   3
01/02/2016  1004    John        0                                   3
01/03/2016  1001    John        2                                   3
01/03/2016  1004    John        0                                   3
01/03/2016  1004    John        1                                   3

如果没有另一个子查询,这可能吗?我想另一种说法是我试图模仿 Powerpivot 的 sumx 和早期功能。

【问题讨论】:

如果您包含预期的输出,那将是一个很大的帮助。 好点,我现在附上。 【参考方案1】:

如果您在 2012 年以上,请使用窗口聚合。 Previous = sum all_previous_including_curret - sum current。 ms sql 默认窗口正好是ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW

with [simple_join_table2] as(
    -- sample data
    select cast(valuesDate as Date) valuesDate, sale_id, salesperson, Missed_payment_this_month 
    from (
        values
         ('20160101',1001,'John', 1)
        ,('20160101',1002,'Bob ', 0)
        ,('20160101',1003,'Bob ', 0)
        ,('20160101',1004,'John',null)
        ,('20160201',1001,'John', 1)
        ,('20160201',1002,'Bob ', 1)
        ,('20160201',1003,'Bob ', 0)
        ,('20160201',1004,'John', 1)
        ,('20160301',1001,'John', 1)
        ,('20160301',1002,'Bob ', 0)
        ,('20160301',1003,'Bob ', 0)
        ,('20160301',1004,'John', 1)
    ) t(valuesDate, sale_id, salesperson, Missed_payment_this_month)
)
select valuesDate,sale_id, salesperson, Missed_payment_this_month, 
  byidprevmonth = sum(Missed_payment_this_month ) over(partition by sale_id order by valuesDate)
        - sum(Missed_payment_this_month) over(partition by valuesDate, sale_id),
  bypersonprevmonth = sum(Missed_payment_this_month) over(partition by salesperson order by valuesDate) 
        - sum(Missed_payment_this_month) over(partition by valuesDate, salesperson)
from [simple_join_table2] 
order by salesperson, valuesDate

【讨论】:

以上是关于简单的 sql over (partition by) 没有按预期工作的主要内容,如果未能解决你的问题,请参考以下文章

在 SQL 中使用 Over 和 Partition

设置列 SQL 的 Over Partition

sql over表示啥意思

count(distinct) over (partition by... 在 Oracle SQL 中不起作用

基于 OVER PARTITION BY 子句的 SQL 计算列

SQL SERVER OVER PARTITION 业务案例