c# - 使用来自一个 DataTable 的数据来获取另一个 DataTable 的结果
问题描述
我目前有一个导出到 DataTable ( dt
) 的存储过程。提供的数据显示了每个客户每月平均拥有的价值。如果数据有要显示的值,则数据必须显示它们的值。
这是我的存储过程(动态数据透视表)的 SQL:
ALTER Procedure [dbo].[stpMonthlyAvg]
--Parameters
AS
Begin
Begin Tran T1;
Begin Try
DECLARE @Dates NVARCHAR(MAX);
SELECT @Dates = CONCAT(@Dates + ', ', QUOTENAME(BalMonth))
FROM vAvgMonBal
GROUP BY BalMonth
ORDER BY BalMonth;
DECLARE @DynSQL NVARCHAR(MAX),
@months NVARCHAR(255);
SET @months = 'CONCAT( CONVERT(nvarchar(15), YEAR(BalDate)) , IIF(LEN(MONTH(BalDate)) > 1, CONVERT(nvarchar(15), MONTH(BalDate)), ''0'' + CONVERT(nvarchar(15), MONTH(BalDate))))'
SET @DynSQL = 'SELECT *
FROM
(SELECT
a1.IDNbr,
a2.CustName, ' + @months + ' AS BalMonth,
AVG(a1.Balance) as Balance
FROM tblID a1
INNER JOIN tblCust a2 ON (a1.IDNbr = a2.IDNbr)
WHERE a2.CustType != ''Inactive'' AND a2.CustType IS NOT NULL AND a1.Balance != 0
GROUP BY
a1.IDNbr, a2.CustName, ' + @months +') as d1
PIVOT (
AVG(Balance)
FOR BalMonth IN (' + @Dates + ')
) piv';
EXECUTE sp_executesql @DynSQL
Commit Tran T1;
End Try
Begin Catch
RollBack Tran T1;
End Catch
End
这是我目前拥有的表的一个示例——带有测试数据:
+-------------------------------------------------------+
| ID | CustName | 201501 | 201502 | 201503 | 201504 | ..|
+-------------------------------------------------------+
| 32 | CustOne | 100.00 | 200.00 | 400.00 | 700.00 | ..|
| 56 | CustTwo | 350.00 | 375.00 | 400.00 | 500.00 | ..|
| 89 | CustThree| 222.22 | 333.33 | 444.44 | 555.55 | ..|
| .. | ... | .. | .. | .. | .. | ..|
+-------------------------------------------------------+
我需要找到每个客户每个月与上个月之间的百分比差异,并将其添加到它自己的 DataTable( fDt
) 中。
这是我需要的(行中的值是百分比):
+-------------------------------------------------------+
| ID | CustName | PerDiff02 | PerDiff03 | PerDiff04 | ..|
+-------------------------------------------------------+
| 32 | CustOne | 0 | 100 | 200 | ..|
| 56 | CustTwo | 93.33 | 93.75 | 80.00 | ..|
| 89 | CustThree| 66.66 | 75.00 | 80.00 | ..|
| .. | ... | .... | .... | .... | ..|
+-------------------------------------------------------+
我目前将数据添加到fDt
,尽管它是按列计算,而不是按行计算(我认为)。
这意味着我的数据输出如下所示:
+-------------------------------------------------------+
| ID | CustName | PerDiff02 | PerDiff03 | PerDiff04 | ..|
+-------------------------------------------------------+
| 32 | CustOne | 0 | 100 | 200 | ..|
| 56 | CustTwo | 0 | 100 | 200 | ..|
| 89 | CustThree| 0 | 100 | 200 | ..|
| .. | ... | .... | .... | .... | ..|
+-------------------------------------------------------+
因为它为整个列分配了一次计算的结果。
这是我正在使用的代码:
Uni.fileExport Export = new Uni.fileExport();
string conStr = "Data Source=" + ConfigurationManager.AppSettings["DataSource"] + "Initial Catalog=" + ConfigurationManager.AppSettings["InitialCatalog"] + "Integrated Security=True;";
var dt = new DataTable();
dt = Export.sqlToDTMonthlyAvg(conStr, stp);
var fDt = new DataTable();
int i;
int fieldCount = dt.Columns.Count;
int finalSize = (fieldCount) * 2;
string[] finalCol = new string[finalSize];
string[] colHeaders = new string[fieldCount];
for (i = 0; i < fieldCount; i++)
{
colHeaders[i] = dt.Columns[i].ToString();
}
fDt.Columns.Add(colHeaders[0]);
fDt.Columns.Add(colHeaders[1]);
for (i = 1; i < dt.Rows.Count; i++)
{
fDt.Rows.Add(dt.Rows[i][0], dt.Rows[i][1]);
}
/*
* This section is meant to try and get the percent difference from dt
* to fDt. Looking into doing this from the SQL data base rather than from the code
* in order to save processing at runTime. The main concern being the stored procedure
* taking longer than a couple minutes.
*/
// Gets the column headers for dataTable fDt
for (i = 2; i <= (dt.Columns.Count - 2); i++)
{
string colName = "PerDiff" + dt.Columns[i + 1];
fDt.Columns.Add(colName, typeof(decimal));
}
for (i = 2; i <= (dt.Columns.Count - 2); i++)
{
var month1 = dt.Columns[i];
var month2 = dt.Columns[i + 1];
fDt.Columns[i].Expression = $"({month1} / {month2}) * 100";
}
问题:如何获得dt
to列的百分比差异fDt
?我需要基于上个月的百分比。
(PerDiff 开始是PerDiff02
因为之前没有任何东西201501
可以比较。)
如果有任何不清楚的地方,请告诉我,我会尽力澄清!我对 C# 还是有点陌生,尤其是datatables
.
我试图在 SQL 中尝试这个,但是我仍然是 SQL 的新手,并且认为这会更容易通过 C# 实现。一旦我让它工作,就会考虑优化。
如果有任何反对意见,我要求您解释为什么反对,以便我更正!
解决方案
好的,这就是我 2 年前为类似的事情所做的
在您的内部选择上添加占位符的差异
SELECT
a1.IDNbr,
a2.CustName, ' + @months + ' AS BalMonth,
AVG(a1.Balance) as Balance,
0 as Diff1,0 as Diff2,0 as Diff3
在 EXECUTE sp_executesql @DynSQL 添加之前
DECLARE @DataProcess TABLE // Table variable to hold everything
(
NewTableID INT IDENTITY(1,1)
, Id INT
, CustName NVARCHAR(256)
, Month1 NVARCHAR(260)
, Month2 NVARCHAR(260)
, Month3 NVARCHAR(260)
, Month4 NVARCHAR(260)
,Diff1 INT
,Diff2 INT
,Diff3 INT
)
INSERT INTO @DataProcess EXECUTE sp_executesql @DynSQL // fill in the data
Now declare values and loop
DECLARE @Count INT, @Counter INT, @Id INT,@Month1 NVARCHAR(260),@Month1 NVARCHAR(260),@Month3 NVARCHAR(260),@Month4 NVARCHAR(260)
SELECT @Count = COUNT(*) FROM @DataProcess d
SET @Counter = 1
BEGIN
SELECT @Id = ID,(260),@Month1 = Month1,@Month2=Month1 ,@Month3=Month3 ,@Month4 =Month3 FROM @DataProcess m WHERE NewTableID = Counter
m.Diff1 =@Month2 - @Month1;
m.Diff2 =@Month3 - @Month2
m.Diff2 =@Month4 - @Month3
SET @Counter = @Counter + 1
END
这应该为您填写所有内容,并且不会使用 sp 破坏任何其他内容
推荐阅读
- python - 翻译文本变量,然后将其放在 tkinter 标签中
- kubernetes - 在 kubernetes 中运行时,docker api 未显示 memoryReservation 值
- python - 有没有在 python 中使用 mod "%" 的替代方法
- shiny - 如何使滑块输入“惰性”并仅在需要时刷新
- python - Keras 中的自动编码器具有低验证损失,但重建只是噪音
- elastalert - CPU 使用率的 Elastalert 规则(百分比)
- jquery - 如何将动态 .next() 函数附加到 jQuery 对象
- c# - 找不到文件:mtbs/builds/z.iOS/yyy/Resources/Images.xcassets/LaunchImages.launchimage/Contents.json
- .net - 出于测试目的,您可以在浏览器中允许混合内容吗?
- c# - 在根目录中获取文件数组的最有效方法(如果存在)