SQL - 从动态 SQL 中获取百分比差异

标签 sql sql-server

我目前有一个动态存储过程,它每个月都在我的数据库中提取数据,然后对每天的值进行平均。

我目前拥有的(值是当月的总体平均值):

+-------------------------------------------------------+
| ID | CustName | 201501 | 201502 | 201503 | 201504 | ..|
+-------------------------------------------------------+
| 32 | CustOne  | 5852.25| 5847.50| 6542.98| 7585.25| ..|
| 56 | CustTwo  | 5452.45| 7852.50| 6985.41| 1245.21| ..|
| 89 | CustThree| 8520.25| 7410.01| 9630.36| 1245.32| ..|
| .. | ...      |   ..   |   ..   |   ..   |   ..   | ..|
+-------------------------------------------------------+

这是我用来创建上表的存储过程:

DECLARE @Dates NVARCHAR(MAX);

SELECT @Dates = CONCAT(@Dates + ', ', QUOTENAME(BalMonth))
FROM vAvgMonBal
GROUP BY BalMonth
ORDER BY BalMonth;

DECLARE @DynSQL NVARCHAR(MAX),
    @months NVARCHAR(MAX);

SET @months = 'CONCAT( CONVERT(nvarchar(15), YEAR(BalDate)) , IIF(LEN(MONTH(BalDate)) > 1, CONVERT(nvarchar(15), MONTH(BalDate)), ''0'' + CONVERT(nvarchar(15), MONTH(BalDate)))) AS BalMonth'
SET @DynSQL = 'SELECT *
           FROM
               (SELECT 
                    a1.IDNbr, 
                    a2.CustName, ' + @months + ',
                    AVG(a1.Balance) as Balance
                FROM tblID a1 
                INNER JOIN tblCust a2 ON (a1.IDNbr = a2.IDNbr)
                WHERE a2.CustType != ''Inactive''
                GROUP BY 
                    a1.IDNbr, a2.CustName, CONCAT( CONVERT(nvarchar(15), YEAR(BalDate)) , IIF(LEN(MONTH(BalDate)) > 1, CONVERT(nvarchar(15), MONTH(BalDate)), ''0'' + CONVERT(nvarchar(15), MONTH(BalDate))))) as d1
PIVOT (
AVG(Balance)
FOR BalMonth IN (' + @Dates + ')
) piv';


EXECUTE sp_executesql @DynSQL

问题:如何从之前的存储过程中获取数据并从中获取百分比差异(Month1/Month2) * 100,如下所示?我预计我将需要一个新的存储过程或添加到我目前拥有的存储过程。

我需要什么(其中每个“PerDiff”是上个月与前表示例的百分比差异):

+---------------------------------------------------------------+
| ID | CustName | PerDiff1 | PerDiff2 | PerDiff3 | PerDiff4 | ..|
+---------------------------------------------------------------+
| 32 | CustOne  |  100.00  |   68.12  |  654.25  |  483.36  | ..|
| 56 | CustTwo  |   58.21  |  154.54  |  932.45  |   58.45  | ..|
| 89 | CustThree|  965.25  |  951.58  |  689.12  |   32.50  | ..|
| .. | ...      |   ....   |   ....   |   ....   |   ....   | ..|
+---------------------------------------------------------------+

我尝试使用类似的东西:

DECLARE @PerDiff nvarchar(max);

SET @PerDiff = 'SELECT *
FROM (' + @DynSQL + ')'

EXECUTE sp_executesql @PerDiff

至少尝试移动数据。

我不再收到任何错误消息——我通常只是停留在如何继续动态应用数学上。

如有任何帮助或建议,我们将不胜感激!

EDIT1:这是最终确定的@DynSQL 的结果

SELECT *
FROM
(
SELECT a1.DDANbr, 
a2.CustName, 
CONCAT( CONVERT(nvarchar(15), YEAR(BalDate)) , IIF(LEN(MONTH(BalDate)) > 1, CONVERT(nvarchar(15), MONTH(BalDate)), '0' + CONVERT(nvarchar(15), MONTH(BalDate))))AS BalMonth,
a1.Balance

FROM tblID a1 INNER JOIN tblCust a2 ON (a1.IDNbr = a2.IDNbr)

WHERE a2.CustType != 'Inactive'

GROUP BY a1.IDNbr, a2.CustName, BalDate, a1.Balance
) as d1
PIVOT (
AVG(Balance)
FOR BalMonth IN ([201501], [201502], [201503], [201504], [201505], [201506], [201507], [201508], [201509], [201510], [201511], [201512], [201601], [201602], [201603], [201604], [201605], [201606], [201607], [201608], [201609], [201610], [201611], [201612], [201701], [201702], [201703], [201704], [201705], [201706], [201707], [201708], [201709], [201710], [201711], [201712], [201801], [201802], [201803], [201804], [201805], [201806], [201807], [201808], [201809])
) piv

最佳答案

当您进行查询并使其成为派生表时,您必须为该表指定一个别名。

像这样:

DECLARE @PerDiff nvarchar(max);

SET @PerDiff = 'SELECT IDNbr, CustName, ' + @months + '
FROM (' + @DynSQL + ') t1'

EXECUTE sp_executesql @DynSQL, @PerDiff

关于SQL - 从动态 SQL 中获取百分比差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52446891/

相关文章:

sql - SQL Server 中数字范围的通配符

C# - 如何将 SQL Server 时间(7)检索到 TimeSpan

mysql - 如何使用order by优化mysql group by

mysql - 在 MySQL 中执行返回多行的子查询?

SQL Server - 查询根据每年的最后值计算加权平均值

SQL逐月检查ID状态变化

sql - 使用 PK 将行插入 SQL Server 表中特定位置

mysql - 我怎样才能让我的代码与3个sql表一起工作?

php - MySQL 为考勤案例选择行

MySQL - 小时(日期时间)