Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
每天获取最新条目/SQL优化_Sql_Sql Server_Tsql_Optimization_Outer Apply - Fatal编程技术网

每天获取最新条目/SQL优化

每天获取最新条目/SQL优化,sql,sql-server,tsql,optimization,outer-apply,Sql,Sql Server,Tsql,Optimization,Outer Apply,给定以下数据库表,该表记录不同对象id的事件状态及其时间戳: ID | Date | Time | Status ------------------------------- 7 | 2016-10-10 | 8:23 | Passed 7 | 2016-10-10 | 8:29 | Failed 7 | 2016-10-13 | 5:23 | Passed 8 | 2016-10-09 | 5:43 | Passed 我想使用纯SQL MS SQL获得一个结果表,如下所

给定以下数据库表,该表记录不同对象id的事件状态及其时间戳:

ID | Date       | Time | Status
-------------------------------
 7 | 2016-10-10 | 8:23 | Passed
 7 | 2016-10-10 | 8:29 | Failed
 7 | 2016-10-13 | 5:23 | Passed
 8 | 2016-10-09 | 5:43 | Passed
我想使用纯SQL MS SQL获得一个结果表,如下所示:

ID | Date       | Status
------------------------
 7 | 2016-10-10 | Failed
 7 | 2016-10-13 | Passed
 8 | 2016-10-09 | Passed
SELECT DISTINCT rn.id,
                tmp.date,
                tmp.status

FROM run rn OUTER apply
  (SELECT rn2.date, tmp2.status AS 'status'
   FROM run rn2 OUTER apply
     (SELECT top(1) rn3.id, rn3.date, rn3.time, rn3.status
      FROM run rn3
      WHERE rn3.id = rn.id
        AND rn3.date = rn2.date
      ORDER BY rn3.id ASC, rn3.date + rn3.time DESC) tmp2
   WHERE tmp2.status <> '' ) tmp
其中,状态是一天中的最新条目,因为至少记录了此对象的一个事件

我当前的解决方案是使用外部应用和TOP1,如下所示:

ID | Date       | Status
------------------------
 7 | 2016-10-10 | Failed
 7 | 2016-10-13 | Passed
 8 | 2016-10-09 | Passed
SELECT DISTINCT rn.id,
                tmp.date,
                tmp.status

FROM run rn OUTER apply
  (SELECT rn2.date, tmp2.status AS 'status'
   FROM run rn2 OUTER apply
     (SELECT top(1) rn3.id, rn3.date, rn3.time, rn3.status
      FROM run rn3
      WHERE rn3.id = rn.id
        AND rn3.date = rn2.date
      ORDER BY rn3.id ASC, rn3.date + rn3.time DESC) tmp2
   WHERE tmp2.status <> '' ) tmp

但是我面临性能问题,因此我认为这个解决方案是不够的。如何解决这个问题或如何优化sql?您的代码似乎太复杂了。为什么不这样做呢

SELECT r.id, r.date, r2.status
FROM run r OUTER APPLY
     (SELECT TOP 1 r2.*
      FROM run r2
      WHERE r2.id = r.id AND r2.date = r.date AND r2.status <> ''
      ORDER BY r2.time DESC
     ) r2;

对于性能,我建议在runid、日期、状态和时间上建立索引。

您的代码似乎太复杂了。为什么不这样做呢

SELECT r.id, r.date, r2.status
FROM run r OUTER APPLY
     (SELECT TOP 1 r2.*
      FROM run r2
      WHERE r2.id = r.id AND r2.date = r.date AND r2.status <> ''
      ORDER BY r2.time DESC
     ) r2;

为了提高性能,我建议在runid、日期、状态、时间上建立索引。

不要从日志表中选择,而是编写一个触发器来更新最新的运行表,如:

CREATE TRIGGER tr_run_insert ON run FOR INSERT AS 
BEGIN
    UPDATE latest_run SET Status=INSERTED.Status WHERE ID=INSERTED.ID AND Date=INSERTED.Date
    IF @@ROWCOUNT = 0
        INSERT INTO latest_run (ID,Date,Status) SELECT (ID,Date,Status) FROM INSERTED
END
然后从更短的最新运行表执行读取。
这将增加写入的性能损失,因为您将需要两次写入而不是一次。但在阅读时会给你更稳定的响应时间。如果不需要从运行表中选择,则可以避免对其编制索引,因此,两次写入的性能损失部分由较少的索引维护来补偿。

不要从日志表中选择,而是编写一个更新最新运行表的触发器,如:

CREATE TRIGGER tr_run_insert ON run FOR INSERT AS 
BEGIN
    UPDATE latest_run SET Status=INSERTED.Status WHERE ID=INSERTED.ID AND Date=INSERTED.Date
    IF @@ROWCOUNT = 0
        INSERT INTO latest_run (ID,Date,Status) SELECT (ID,Date,Status) FROM INSERTED
END
然后从更短的最新运行表执行读取。
这将增加写入的性能损失,因为您将需要两次写入而不是一次。但在阅读时会给你更稳定的响应时间。如果不需要从运行表中进行选择,则可以避免对其进行索引,因此,两次写入的性能损失部分由较少的索引维护来补偿。

使用CTE可能是最快的:

with cte as 
(
    select ID, Date, Status, row_number() over (partition by ID, Date order by Time desc) rn
    from run
)
select ID, Date, Status 
from cte
where rn = 1

使用CTE可能是最快的:

with cte as 
(
    select ID, Date, Status, row_number() over (partition by ID, Date order by Time desc) rn
    from run
)
select ID, Date, Status 
from cte
where rn = 1

谢谢你的建议,但这是一个商业应用程序,我不允许更改。谢谢你的建议,但这是一个商业应用程序,我不允许更改。太好了,这个小小的更改-我太盲目了,看不见-使代码运行快了8倍。谢谢!太好了,这个小小的改变——我太盲目了,看不见——使代码运行速度提高了8倍。谢谢!