2016-09-30 39 views
0

我計算C#Winforms中的優秀客戶餘額。下面的代碼有效,但速度很慢。有什麼辦法可以改善它的表現嗎?C#中的MS SQL查詢 - 性能較差

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(); 
    } 
} 
+1

那麼這部分是慢?你爲什麼要捕捉一個*有用的*異常,只是拋出一個沒有任何信息的異常呢? –

+0

爲什麼2個SQL命令? –

+2

(從根本上看,問題在於你正在做N + 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); 
      } 
     } 
    } 

您可以修改的方法,並通過代碼作爲參數

+0

謝謝,它的工作........... –

+0

http://stackoverflow.com/questions/39858074/how-customise-nop-commerce-ewayhosted-plugin-for-other-payment-gateway –

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,通過代碼分組

指數代碼列

+0

我嘗試加入查詢,但沒有成功。請舉例說明我的代碼。 –