Mysql SQL查询-按到期月份透视贷款汇总

Mysql SQL查询-按到期月份透视贷款汇总,mysql,sql,pivot,Mysql,Sql,Pivot,这看起来很简单,但我正使劲把头撞到墙上想弄明白 我有一个单一的贷款数据表,我想重点分析和总结每个月的付款到期。这类似于“静态池分析”,将每个贷款池作为行,月份作为列。您可以使用以下命令查看示例数据 如果有帮助的话,我已经创建了一个例子来更好地解释我需要的重点和总结结果。谢谢你的帮助 如果不需要是动态的,则使用SUM中的CASE-WHEN或If语句作为MySQL中的枢轴: SELECT PoolMonth, SUM(OriginationAmt) AS Origination, S

这看起来很简单,但我正使劲把头撞到墙上想弄明白

我有一个单一的贷款数据表,我想重点分析和总结每个月的付款到期。这类似于“静态池分析”,将每个贷款池作为行,月份作为列。您可以使用以下命令查看示例数据


如果有帮助的话,我已经创建了一个例子来更好地解释我需要的重点和总结结果。谢谢你的帮助

如果不需要是动态的,则使用SUM中的CASE-WHEN或If语句作为MySQL中的枢轴:

SELECT 
  PoolMonth, 
  SUM(OriginationAmt) AS Origination,
  SUM(IF(PmtDue = 201512, AmtPaid, 0)) AS `201512`,
  SUM(IF(PmtDue BETWEEN 201512 AND 201601, AmtPaid, 0)) AS `201601`,
  SUM(IF(PmtDue BETWEEN 201512 AND 201602, AmtPaid, 0)) AS `201602`
FROM
  Loans
GROUP BY
  PoolMonth;

这有点冗长,无法获取total OriginationAmt、PoolMonth/PmtDue的运行总数,并且只输出最新的运行总数,而不进行任何硬编码,但我们现在开始:-)


从这里开始,在Excel或其他任何地方查看结果都应该非常容易。

感谢您花时间回答。是的,这是可行的,但是,正如您所注意到的,我的场景是动态的,PmtDue列中的月份不一样,这就是为什么需要该列上的透视。我将在稍后更新我的答案,但您基本上是在寻找这个:我通常在查询中避免使用动态SQL,因为它很难阅读,而且我通常可以更清楚地将这种动态数据透视移动到应用程序层(Excel、Tableau、Web应用程序等)。我实际上可以使用Excel来透视数据,只要数据可以以同样的方式汇总。Excel将允许我稍后在数据上添加过滤器。这将使您的输出更易于操作,而无需单独指定范围。
SELECT
  t.PoolMonth,
  t.TtlOriginationAmt,
  t.PmtDue,
  t.RtAmtPaid
FROM
  (
    SELECT 
      l.PoolMonth,
      l.OriginationAmt,
      orig.TtlOriginationAmt,
      l.PmtDue,
      /* Row_Number() equivalent for MySQL http://blog.sqlauthority.com/2014/03/09/mysql-reset-row-number-for-each-group-partition-by-row-number/ */
      /* Assign a Row Number for each Payment Due month for the individual Pool month in ascending order (ORDER BY clause important in this subquery) */
      @RowNumber := CASE WHEN @PoolMonth = l.PoolMonth AND @PmtDue = l.PmtDue THEN @RowNumber + 1 ELSE 1 END AS PoolPmtRowNumber,
      /* Use the total count of PmtDue month rows for each PoolMonth so we can limit our results to the final row */
      lr.PoolPmtLastRow,
      l.AmtPaid,
      /* Running total of Amount Paid for the individual Pool month in order of Payment Due month (ORDER BY clause important in this subquery) */
      @RtAmtPaid := CASE WHEN @PoolMonth = l.PoolMonth THEN @RtAmtPaid + l.AmtPaid ELSE l.AmtPaid END AS RtAmtPaid,
      /* Keep track of the Pool month we're totalling */
      @PoolMonth := l.PoolMonth,
      /* Keep track of the Payment Due month we're ordering */
      @PmtDue := l.PmtDue
    FROM
      Loans l
    JOIN
      /* Get the Total Origination Amount */
      (SELECT PoolMonth, SUM(OriginationAmt) AS TtlOriginationAmt FROM Loans GROUP BY PoolMonth) orig ON orig.PoolMonth = l.PoolMonth
    JOIN
      /* Get the total number of records by Pool/Payment due month so we can filter to the last row */
      (SELECT PoolMonth, PmtDue, COUNT(1) AS PoolPmtLastRow FROM Loans GROUP BY PoolMonth, PmtDue) AS lr ON lr.PoolMonth = l.PoolMonth AND lr.PmtDue = l.PmtDue
    CROSS JOIN
      /* Reset the variables we need for tracking */
      (SELECT @RtAmtPaid:=0,@PoolMonth:=0,@PmtDue:=0,@RowNumber:=0) var
    /* Order by Pool/Payment Due month */
    ORDER BY
      l.PoolMonth,
      l.PmtDue
  )t
WHERE
  /* Filter to the last row */
  t.PoolPmtRowNumber = t.PoolPmtLastRow;