查找最近过期的日期

时间:2019-02-06 13:08:04

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

我有以下问题:从工资表中,我需要找到上次逾期的日期。例如,这是表格和数据:

<TouchableOpacity
  style={styles.buttonText}
  onPress={()=>this.props.navigation.navigate('AirLineSearchResult')}
  >
    <View style={styles.buttonContainer}>
      <Text
        style={styles.okBotton}
        >جست و جو</Text>
    </View>
</TouchableOpacity>

如果“ Sum”的值为正-表示过期已开始;如果“总和”为负数,则表示有人为此交易付款。

在上面关于“ 122222”交易的示例中,逾期从2017年12月13日开始,到2017年12月29日结束,因此不应出现在结果中。

对于“ 222221”交易,始于2017-11-20的第一个25,000的逾期款项已于2017-11-28支付完毕,所以当前逾期(我们感兴趣)的最后日期是2017-12- 31

我已选择此选项以汇总所有付款,并停留在此处:(

create table t (
    Id int
  , [date] date
  , Customer varchar(6)
  , Deal varchar(6)
  , Currency varchar(3)
  , [Sum] int
);

insert into t values
  (1, '2017-12-12', '1110', '111111', 'USD', 12000)
, (2, '2017-12-25', '1110', '111111', 'USD', 5000)
, (3, '2017-12-13', '1110', '122222', 'USD', 10000)
, (4, '2018-01-13', '1110', '111111', 'USD', -10100)
, (5, '2017-11-20', '2200', '222221', 'USD', 25000)
, (6, '2017-12-20', '2200', '222221', 'USD', 20000)
, (7, '2017-12-31', '2201', '222221', 'USD', -10000)
, (8, '2017-12-29', '1110', '122222', 'USD', -10000)
, (9, '2017-11-28', '2201', '222221', 'USD', -30000);

如果没有0或负的Debt_balance,显然我需要(对于每个交易)查找最少的Dates,否则,最后一个0余额之后的下一个日期。

对于有关该主题的任何提示和想法将不胜感激。 谢谢!

更新 我的解决方案版本:

WITH cte AS (
    SELECT *,
            SUM([Sum]) OVER(PARTITION BY Deal ORDER BY [Date]) AS Debt_balance
    FROM t
)

2 个答案:

答案 0 :(得分:1)

您可以使用窗口功能。这些可以计算中间值:

  • 最后一天的总和为负数(即最后的“好”记录)。
  • 最后一笔

然后您可以将它们结合起来

select deal, min(date) as last_overdue_start_date
from (select t.*,
             first_value(sum) over (partition by deal order by date desc) as last_sum,
             max(case when sum < 0 then date end) over (partition by deal order by date) as max_date_neg
      from t
     ) t
where last_sum > 0 and date > max_date_neg
group by deal;

实际上,不需要最后一个日期的值。因此,简化为:

select deal, min(date) as last_overdue_start_date
from (select t.*,
             max(case when sum < 0 then date end) over (partition by deal order by date) as max_date_neg
      from t
     ) t
where date > max_date_neg
group by deal;

答案 1 :(得分:1)

我相信您正在尝试使用连续求和并跟踪它何时变为正值,并且它可能多次变为正值,并且您希望它变为正值的最后日期。除了运行总和,您还需要LAG()

WITH cte1 AS (
    -- running balance column
    SELECT *
         , SUM([Sum]) OVER (PARTITION BY Deal ORDER BY [Date], Id) AS RunningBalance
    FROM t
), cte2 AS (
    -- overdue begun column - set whenever running balance changes from l.t.e. zero to g.t. zero
    SELECT *
         , CASE WHEN LAG(RunningBalance, 1, 0) OVER (PARTITION BY Deal ORDER BY [Date], Id) <= 0 AND RunningBalance > 0 THEN 1 END AS OverdueBegun
    FROM cte1
)
-- eliminate groups that are paid i.e. sum = 0
SELECT Deal, MAX(CASE WHEN OverdueBegun = 1 THEN [Date] END) AS RecentOverdueDate
FROM cte2
GROUP BY Deal
HAVING SUM([Sum]) <> 0

Demo on db<>fiddle