C# 查询优化或在ViewModel中的DoWork中缓慢填充ObservableObject

C# 查询优化或在ViewModel中的DoWork中缓慢填充ObservableObject,c#,mysql,wpf,C#,Mysql,Wpf,以下是我的表格中的表格列: EmpNo = Employee number of the creator of the row DateReceived = the datetime when the ticket is received by employee DateProcessed = the date the row is inserted Workcode = ticket name TimeStart = the datetime the ticket started TimeEn

以下是我的表格中的表格列:

EmpNo = Employee number of the creator of the row
DateReceived = the datetime when the ticket is received by employee
DateProcessed = the date the row is inserted
Workcode = ticket name
TimeStart = the datetime the ticket started
TimeEnd = the datetime the ticket ended

我需要获得每笔交易的
ElapsedTime
周转时间

ElapsedTime = TimeEnd - TimeStart
TurnAroundTime = SUM (TIMESTAMPDIFF(MINUTE, TimeStart, TimeEnd)) 
                WHERE EmpNo = @emp AND TimeStart BETWEEN @datereceived AND @timeend

    => in short TurnAroundTime is the sum of all the elapsedtime 
    of all the rows created by employee from datereceived to timeend
以下是我正在使用的查询:

SELECT `Id`, `EmpNo`, `DateProcessed`, `Workcode`, 
`DateReceived`, `TimeStart`, `TimeEnd`, 
TIMESTAMPDIFF(MINUTE, TimeStart, TimeEnd) ElapsedTime,
CASE
    WHEN DateReceived = '0001-01-01' OR 
         DateReceived = '0000-00-00' OR 
         DateReceived IS NULL THEN 0
    ELSE get_tat(EmpNo, DateReceived, TimeEnd)
END AS TurnAroundTime
FROM table1 WHERE DateProcessed BETWEEN '2014-04-01' AND '2014-04-23';
下面是查询中使用的
get\u tat()
函数:

FUNCTION `get_tat`(_empno VARCHAR(6), _dateReceived DATETIME, _timeEnd DATETIME) RETURNS INT(11)
BEGIN
    DECLARE var_return INT;

    SELECT SUM(TIMESTAMPDIFF(MINUTE, TimeStart, TimeEnd)) INTO var_return
    FROM table1 WHERE Empno = _empno AND TimeStart BETWEEN _dateReceived AND _timeEnd;

    RETURN var_return;
END$$
问题是查询需要30秒以上的时间才能完成执行。有人能给我解释一下如何优化这个查询吗

此外,我还设置了一个索引:

 INDEX (`EmpNo`, `DateProcessed`, `Workcode`, `TimeStart`)
我的一位朋友告诉我,我需要优化
get_tat
函数,但我没有提示如何启动它。请帮忙。谢谢!:)

--编辑--

在Gordon的帮助下优化了我的代码。从平均执行时间30秒到现在的平均时间约为6-8秒。:)

我在ViewModel中填充DataGrid,发现我的c代码中有什么太慢了。我正在像这样填充ObservableCollection:

App.Current.Dispatcher.Invoke(new Action(() => _finishedTransactions.Add(x)));
这是在
ViewModel
中的
DoWork()
内部调用的,因此我不能使用简单的:

_finishedTransactions.Add(x);
它抛出:

This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread.
\u finishedTransaction
可观察到的集合

我调试了这部分代码,发现这需要时间:

foreach (DataRow row in data.Rows)
{
    var x = new FinishedTransactionModel(row);
    App.Current.Dispatcher.Invoke(new Action(() => _finishedTransactions.Add(x)));
}
您的基本查询是:

SELECT . . .
       (CASE WHEN DateReceived = '0001-01-01' OR 
                  DateReceived = '0000-00-00' OR 
                  DateReceived IS NULL THEN 0
              ELSE (SELECT SUM(TIMESTAMPDIFF(MINUTE, TimeStart, TimeEnd))
                    FROM table1 t2
                    WHERE t2.Empno = t1.empno AND
                          t2.TimeStart BETWEEN t1.dateReceived AND t1.timeEnd
                   )
        END) AS TurnAroundTime
FROM table1 t1
WHERE DateProcessed BETWEEN '2014-04-01' AND '2014-04-23';
现在我再仔细看一下,子查询/函数的索引应该是
table1(EmpNo、TimeStart、TimeEnd)

对于此查询,您需要在
table1(DateProcessed)
上建立索引

该函数的查询是:

SELECT SUM(TIMESTAMPDIFF(MINUTE, TimeStart, TimeEnd)) INTO var_return
FROM table1
WHERE Empno = _empno AND TimeStart BETWEEN _dateReceived AND _timeEnd;
您现有的索引对此应该是正确的

如果不需要该函数,您可能会发现将它们组合到一个查询中(而不是使用函数调用)更有效

编辑:

组合查询如下所示:

SELECT `Id`, `EmpNo`, `DateProcessed`, `Workcode`, 
       `DateReceived`, `TimeStart`, `TimeEnd`, 
       TIMESTAMPDIFF(MINUTE, TimeStart, TimeEnd) ElapsedTime,
       (CASE WHEN DateReceived = '0001-01-01' OR 
                  DateReceived = '0000-00-00' OR 
                  DateReceived IS NULL THEN 0
             ELSE get_tat(EmpNo, DateReceived, TimeEnd)
        END) AS TurnAroundTime
FROM table1
WHERE DateProcessed BETWEEN '2014-04-01' AND '2014-04-23';

您可以通过设置时间限制(50)来增加脚本的默认执行时间;在查询前使用。

查询将对时间戳数据进行整整一个月的查询。有时,没有调谐的地方。你应该缩小你的日期处理范围。谢谢@Gordon。我添加了索引(DateProcessed),并将查询和函数组合到单个查询中,但仍然相同。平均执行时间为30.04秒。我试图解释每个SELECT语句,但在子查询中,即使删除索引,我也会得到相同的行。