2015-11-20 61 views
1

所以之間計算時間跨度......我有這樣的AA表:提高SQL查詢連續兩行

RowID | DocID | Time  | DepartmentID 
1  | 1001 | 2015-11-20 | 1 
2  | 1001 | 2015-11-21 | 2 
3  | 1002 | 2015-11-20 | 1 
4  | 1001 | 2015-11-25 | 1 
5  | 1002 | 2015-11-22 | 3 
6  | 1002 | 2015-11-30 | 1 

我的目標是將其發送到之前得到一個部門與文檔花費幾天的時間另一個部門。

我成功實現了這一點,將上表中的數據從SQL傳遞到C#中的數據表。然後獲取DocsID的列表,並迭代拋出每個項目在列表中過濾數據表與DocID,然後才計算連續行之間的時間。 所以最後的結果是這樣的:

DepartmentID | DocID | Time (Days) 
1   | 1001 | 2 
2   | 1001 | 5 
1   | 1002 | 3 
3   | 1002 | 9 

問題是這樣的功能在C#正在約30秒,以得到這個結果,所以我在尋找方法來改善它。
是否有可能得到這個拋出SQL而不做任何事情在C#中?

我的C#函數(DT是第一個表數據表):

 List<Int32> listDocIDs = new List<Int32>(); 
     foreach (DataRow dr in dt.Rows) 
     { 
      int str = Convert.ToInt32(dr["DocID"].ToString()); 

      if (!listDocIDs.Contains(str)) 
       listDocIDs.Add(str); 
     } 

     DataTable times = new DataTable(); 

     times.Columns.AddRange(new DataColumn[3] { new DataColumn("DepartmentID", typeof(Int32)), 
         new DataColumn("DocID",typeof(Int32)), 
         new DataColumn("Days",typeof(Int32)) }); 

     foreach (int DocID in listDocIDs) 
     { 
      DataTable DocID_times = new DataTable(); 

      using (SqlConnection conn = new SqlConnection(strCon)) 
      { 
       conn.Open(); 
       SqlDataAdapter adapter = new SqlDataAdapter("getRecordsByDocID", conn); 
       adapter.SelectCommand.Parameters.Add("@DocID", SqlDbType.Int).Value = DocID; 
       adapter.SelectCommand.CommandType = CommandType.StoredProcedure; 
       adapter.Fill(DocID_times); 
       conn.Close(); 
      } 

      int j = 0; 
      for (int i = 0; i < DocID_times.Rows.Count; i++) 
      { 
       j = i + 1; 

       if (i < (DocID_times.Rows.Count - 1)) 
       { 
        DateTime tempo1 = DateTime.ParseExact(DocID_times.Rows[i]["Time"].ToString(), "dd-MM-yyyy HH:mm:ss", 
            System.Globalization.CultureInfo.InvariantCulture); 
        DateTime tempo2 = DateTime.ParseExact(DocID_times.Rows[j]["Time"].ToString(), "dd-MM-yyyy HH:mm:ss", 
            System.Globalization.CultureInfo.InvariantCulture); 

        double mins = (tempo2 - tempo1).TotalMinutes; 
        TimeSpan result = TimeSpan.FromMinutes(mins); 
        double days = result.TotalDays; 

        var rows = times.Select(string.Format("DepartmentID = {0} AND DocID = {1}", DepartmentID, DocID)); 
        if (rows.Length == 0) 
        { 
         // Add your Row 
         times.Rows.Add(DepartmentID, DocID, days);  
        } 
        else 
        { 
         // Update your Days 
         rows[0]["days"] = Convert.ToInt32(rows[0]["days"].ToString()) + days; 
        } 

       } 
      } 
     } 
+1

問題不清楚。我認爲它是一個搜索算法問題。請顯示您正在使用的查詢。您只顯示輸入和輸出。請告訴你如何使用輸入來獲得此輸出。 –

+0

你如何知道你的SQL查詢需要更多時間?可能是你的c#功能正在採取更多,但不是查詢?可能你有你的代碼需要更多時間的某種嵌套循環?請張貼C#代碼以及SQL查詢......... – Viru

+0

我回顧了我的問題,現在更清楚了嗎?需要花費時間的是我用C#構建的從輸入到輸出的函數。 – iamdlm

回答

0

如果你列出所有的行,我會計算while循環中記錄之間的天數。它可以純粹用SQL來完成,但它不會像while循環(每次可以訪問兩行)一樣好。爲了能夠純粹用SQL來完成,你必須將自己加入到表中,並將每個記錄與下一個記錄聯繫起來。

IEnumerable<MySummarizedRow> GetSummarizedRows() 
{ 
    using (var entries = GetRowsOrderedByDocIdAndRowId().GetEnumerator()) 
    { 
     if (entries.MoveNext()) 
     { 
      var previous = entries.Current; 
      while (entries.MoveNext()) 
      { 
       var current = entries.Current; 
       if (current.DocId == previous.DocId) 
        yield return new MySummarizedRow(previous.DepartmentId, current.DocId, current.Time.Substract(previous.Time).TotalDays + 1); 

       previous = current; 
      } 
     } 
    } 
} 

此函數忽略尚未傳遞給其他部門的文檔的行。你可以很容易地改變產生-1天的新行或類似的東西。