我在C#Winforms中计算出色的客户余额。下面的代码有效,但速度很慢。有没有办法改善其表现?
public DataTable GetOutStandingCustomers()
{
decimal Tot = 0;
DataTable table = new DataTable();
SqlConnection con = null;
try
{
table.Columns.Add("Code", typeof(Int32));
table.Columns.Add("Name", typeof(string));
table.Columns.Add("City", typeof(string));
table.Columns.Add("Tot", typeof(decimal));
string constr = ConfigHelper.GetConnectionString();
string query = "SELECT Code, Name,City FROM Chart WHERE LEFT(CODE,3)='401' AND Code > 401001 ";
string query0 = " SELECT(SELECT ISNULL( SUM(SalSum.Grand),'0' ) FROM SalSum WHERE SalSum.Code = @Code ) +( SELECT ISNULL(SUM(Journals.Amount),'0' ) FROM Journals WHERE Journals.DrCode = @Code ) -( SELECT ISNULL(SUM(RSalSum.Grand),'0' ) FROM RSalSum WHERE RSalSum.Code = @Code ) -( SELECT ISNULL(SUM(Journals.Amount),'0' ) FROM Journals WHERE Journals.CrCode = @Code )+(SELECT ISNULL(SUM(Chart.Debit),'0' ) FROM Chart WHERE Chart.Code = @Code) - (SELECT ISNULL(SUM(Chart.Credit), '0') FROM Chart WHERE Chart.Code = @Code)";
Person per = new Person();
con = new SqlConnection(constr);
SqlCommand com = new SqlCommand(query, con);
SqlCommand com0 = new SqlCommand(query0, con);
con.Open();
SqlDataReader r = com.ExecuteReader();
if (r.HasRows)
{
while (r.Read())
{
per.Name = Convert.ToString(r["Name"]);
per.City = Convert.ToString(r["City"]);
per.Code = Convert.ToString(r["Code"]);
com0.Parameters.Clear();
com0.Parameters.Add("@Code", SqlDbType.Int).Value = per.Code;
Tot = Convert.ToDecimal(com0.ExecuteScalar());
if (Tot != 0)
{
table.Rows.Add(per.Code, per.Name, per.City, Tot);
}
}
}
r.Close();
con.Close();
return table;
}
catch (Exception)
{
throw new Exception();
}
}
答案 0 :(得分:0)
在这种情况下,您似乎正在循环并使用多个代码执行多个查询,您还要两次查询图表。在这种情况下,您需要使用Chart中的LEFT JOIN
到其他表格。
ON Chart.Code = Salsum.Code
ON Chart.Code = Journal.Code
例如,。
您还必须查看GROUP BY
,因为您使用SUM
汇总了一些表格列。
您可能还需要确保在您查询的表中索引代码。只要经常像这样查询代码并且相对很少更新或插入代码,那么在这些表上索引代码列可能是合适的。
左连接:https://technet.microsoft.com/en-us/library/ms187518(v=sql.105).aspx
建立索引:https://technet.microsoft.com/en-us/library/jj835095(v=sql.110).aspx
抱歉,我在这里写了一本关于你的书,但优化通常会导致很长的答案(尤其是SQL)。
tldr; 使用LEFT JOIN,按代码分组
索引代码列
答案 1 :(得分:0)
性能问题是由于您从服务器检索所有数据并使用从七个表中求和的复杂计算表达式过滤客户端中的数据:
if (Tot != 0)
{
table.Rows.Add(per.Code, per.Name, per.City, Tot);
}
这表示网络上的开销加上您手动将结果逐行添加到数据表中。
提供的解决方案使用CROSS APPLY根据计算的表达式在服务器中进行过滤 并直接从DataReader自动创建数据表。
CROSS APPLY的好处是所有列对主sql查询都是可行的,因此可以在ToT列上进行过滤,过滤在服务器(而不是客户端)中完成。
public void SelctChart()
{
string sql2 = @"
select c.Code, c.Name,c.City ,oo.T
from chart c
cross apply
( select c.code,
(
(select ISNULL( SUM(SalSum.Grand),0 ) FROM SalSum WHERE SalSum.Code = c.code )
+( select ISNULL(SUM(j.Amount),0 ) FROM [dbo].[Jornals] j WHERE j.DrCode = c.code)
-( SELECT ISNULL(SUM(RSalSum.Grand),'0' ) FROM RSalSum WHERE RSalSum.Code = c.Code )
-( SELECT ISNULL(SUM(j.Amount),0 ) FROM [dbo].[Jornals] j WHERE j.CrCode = c.code )
+(SELECT ISNULL(SUM( c0.Debit),0 ) FROM [dbo].Chart c0 WHERE c0.Code = c.code)
- (SELECT ISNULL(SUM(c1.Credit), 0) FROM [dbo].Chart c1 WHERE c1.Code = c.code)
)T
) oo
where
oo.T >0
and LEFT(c.CODE,3)='401' AND c.Code > 401001
";
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand(sql2, connection);
//in case you pass @code as a a parameter
//command.Parameters.Add("@code", SqlDbType.Int);
//command.Parameters["@code"].Value = code;
try
{
connection.Open();
var reader = command.ExecuteReader();
while (!reader.IsClosed)
{
DataTable dt = new DataTable();
// Autoload datatable
dt.Load(reader);
Console.WriteLine(dt.Rows.Count);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
您可以修改方法并将代码作为参数传递