[英]Sql Query Pervious Row Optimisation
這是我的表結構
MyTable
-----------
ObjectID int (Identity), -- Primary Key
FileName varchar(10),
CreatedDate datetime
...........
...........
...........
我需要花時間在文件中創建記錄...即...同一文件中的上一條記錄與同一文件的當前記錄之間經過的時間
即...如果記錄是
ObjectID FileName CreatedDate (just showing the time part here)
-------- -------- -----------
1 ABC 10:23
2 ABC 10:25
3 DEF 10:26
4 ABC 10:30
5 DEF 10:31
6 DEF 10:35
所需的輸出是...
ObjectID FileName CreatedDate PrevRowCreatedDate
-------- -------- ----------- ---------------
1 ABC 10:23 NULL
2 ABC 10:25 10:23
3 DEF 10:26 NULL
4 ABC 10:30 10:25
5 DEF 10:31 10:26
6 DEF 10:35 10:31
到目前為止,我得到了這個查詢,但是它花費的時間比預期的要長。有更好的方法嗎?
Select A.ObjectID,
A.FileName
A.CreatedDate as CreatedDate,
B.PrevRowCreatedDate,
datediff("SS", '1900-01-01 00:00:00', Coalesce((A.CreatedDate - B.PrevRowCreatedDate),0)) as secondsTaken
from MyTable as A
Cross Apply (
(Select PrevRowCreatedDate = Max(CreatedDate) from MyTable as BB
where BB.FileName = A.FileName and
BB.CreatedDate < A.CreatedDate
)
) as B
如果您需要更多信息,請告訴我
謝謝
SELECT t1.FileName, t1.CreatedDate, t2.CreatedDate as PrevCreatedDate
FROM
(SELECT FileName, CreateDate,
ROW_NUMBER() OVER(PARTITION BY FileName ORDER BY CreatedDate) AS OrderNo
FROM MyTable) t1
LEFT JOIN
(SELECT FileName, CreateDate,
ROW_NUMBER() OVER(PARTITION BY FileName ORDER BY CreatedDate) AS OrderNo
FROM MyTable) t2
ON (t1.FileName = t2.FileName AND t1.OrderNo = t2.OrderNo - 1)
或者最好使用“ WITH”,因為查詢是相同的:
WITH t(ObjectID, FileName, CreatedDate, OrderNo) AS
(SELECT ObjectID, FileName, CreatedDate,
ROW_NUMBER() OVER(PARTITION BY FileName ORDER BY CreatedDate) AS OrderNo
FROM MyTable)
SELECT t1.ObjectID, t1.FileName, t1.CreatedDate, t2.CreatedDate AS PrevCreatedDate,
DATEDIFF("SS", '1900-01-01 00:00:00',
COALESCE((t1.CreatedDate - t2.CreatedDate),0)) AS secondsTaken
FROM t t1 LEFT JOIN t t2
ON (t1.FileName = t2.FileName AND t1.OrderNo = t2.OrderNo + 1)
我認為Michael的回答確實應該更有效。 盡管在評估效率時,我只想提請注意Management Studio中顯示的查詢成本(相對於批次)的問題。
我建立了一個包含23,174行的測試表,並在問題和邁克爾的問題中運行了查詢。 查看實際執行計划中的“查詢成本(相對於批次)”,原始查詢為1%,邁克爾的成本為99%,因此效率極低。
但是實際數據卻完全不同
SQL Server執行時間:CPU時間= 0毫秒,經過的時間= 0毫秒。
表“ MyTable”。 掃描計數23175 ,邏輯讀取49335 ,物理讀取0,預讀讀取0,lob邏輯讀取0,lob物理讀取0,lob提前讀取0。
SQL Server執行時間:CPU時間= 391毫秒,經過的時間= 417毫秒。
表“工作表”。 掃描計數0,邏輯讀0,物理讀0,預讀0,lob邏輯讀0,lob物理讀0,lob預讀0。
表“ MyTable”。 掃描計數2,邏輯讀148,物理讀0,預讀0,lob邏輯讀0,lob物理讀0,lob預讀0。
在ROW_NUMBER
計划中, rownumber=rownumber+1
上的Merge Join有23,174行進入雙方。 此值是唯一的,實際的行數也為23,174。 但是,SQL Server估計從該聯接產生的行將為34,812,000,因此其在計划中稍后插入的估計成本非常不准確。
BEGIN TRAN
CREATE TABLE MyTable
(
[ObjectID] [INT] IDENTITY(1, 1) NOT NULL PRIMARY KEY CLUSTERED,
[FileName] [VARCHAR](50) NULL,
[CreatedDate] [DATETIME] NULL
)
GO
INSERT INTO MyTable
SELECT ISNULL(type, NEWID()),
DATEADD(DAY, CAST(RAND(CAST(NEWID() AS VARBINARY)) * 10000 AS INT), GETDATE())
FROM master.dbo.spt_values,
(SELECT TOP 10 1 AS X FROM master.dbo.spt_values) V
DELETE FROM MyTable
WHERE EXISTS(SELECT *
FROM MyTable m2
WHERE MyTable.CreatedDate = m2.CreatedDate
AND MyTable.FileName = m2.FileName
AND MyTable.ObjectID < m2.ObjectID)
CREATE UNIQUE NONCLUSTERED INDEX [IX_MyTable]
ON MyTable ([FileName] ASC, [CreatedDate] ASC)
SET STATISTICS IO ON
SET STATISTICS TIME ON
SELECT A.ObjectID,
A.FileName,
A.CreatedDate AS CreatedDate,
B.PrevRowCreatedDate,
DATEDIFF("SS", '1900-01-01 00:00:00', COALESCE(( A.CreatedDate - B.PrevRowCreatedDate ), 0)) AS secondsTaken
INTO #A
FROM MyTable AS A
CROSS APPLY ((SELECT PrevRowCreatedDate = MAX(CreatedDate)
FROM MyTable AS BB
WHERE BB.FileName = A.FileName
AND BB.CreatedDate < A.CreatedDate)) AS B;
WITH t(ObjectID, FileName, CreatedDate, OrderNo)
AS (SELECT ObjectID,
FileName,
CreatedDate,
RANK() OVER(PARTITION BY FileName ORDER BY CreatedDate) AS OrderNo
FROM MyTable)
SELECT t1.ObjectID,
t1.FileName,
t1.CreatedDate,
t2.CreatedDate AS PrevCreatedDate,
DATEDIFF("SS", '1900-01-01 00:00:00', COALESCE(( t1.CreatedDate - t2.CreatedDate ), 0)) AS secondsTaken
INTO #B
FROM t t1
LEFT JOIN t t2
ON ( t1.FileName = t2.FileName
AND t1.OrderNo = t2.OrderNo + 1 )
/*Test the 2 queries give the same result*/
SELECT *
FROM #A
EXCEPT
SELECT *
FROM #B
SELECT *
FROM #B
EXCEPT
SELECT *
FROM #A
ROLLBACK
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.