Wendelius
I want to get the last id with max date
Из вашего вопроса у меня сложилось впечатление, что одна дата может иметь несколько строк, содержащих разные значения в TransId. Если это так, то вы должны убедиться, что действительно извлекаете самое высокое значение идентификатора. Для этого вам нужно добавить дополнительные условия или сортировку, чтобы выбрать правильное значение.
Модифицированный из запросов, уже предоставленных в предыдущем посте, вы можете использовать что-то вроде
-- [=====[ Option 1 ]=====]
SELECT TOP 1
TransID, [Date]
FROM #RNT1
ORDER BY [Date] DESC,
TransID DESC
-- [=====[ Option 2 ]=====]
SELECT TOP 1
TransID, [Date]
FROM #RNT1
WHERE [Date]= (SELECT Max([Date]) FROM #RNT1)
ORDER BY TransID DESC
Чтобы добавить некоторые данные в разговор о производительности, вы можете создать несколько тестовых строк:
CREATE TABLE #RNT1 (
TransID CHAR(10) NOT NULL ,
[Date] Date NULL
)
DECLARE @counter int
BEGIN
SET @counter = 1;
WHILE @counter < 10000000
BEGIN
INSERT INTO #RNT1 VALUES (RAND()*1000000, GETDATE()-RAND()*500);
SET @counter = @counter + 1;
END;
END;
Если вы исследуете планы, они выглядят совсем по-другому
Option 1
--------
|--Sort(TOP 1, ORDER BY:([tempdb].[dbo].[#RNT1].[Date] DESC, [tempdb].[dbo].[#RNT1].[TransID] DESC))
|--Table Scan(OBJECT:([tempdb].[dbo].[#RNT1]))
Option 2
--------
|--Sort(TOP 1, ORDER BY:([tempdb].[dbo].[#RNT1].[TransID] DESC))
|--Nested Loops(Inner Join, WHERE:([Expr1006]=[tempdb].[dbo].[#RNT1].[Date]))
|--Stream Aggregate(DEFINE:([Expr1006]=MAX([tempdb].[dbo].[#RNT1].[Date])))
| |--Table Scan(OBJECT:([tempdb].[dbo].[#RNT1]))
|--Table Scan(OBJECT:([tempdb].[dbo].[#RNT1]))
Итак, каков же эффект на практике, когда тестовые случаи, сгенерированные выше, выполняются почти одинаково
Option 1
--------
Table '#RNT1'. Scan count 1, logical reads 28572, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 1515 ms, elapsed time = 1525 ms.
Option 2
--------
SQL Server parse and compile time:
CPU time = 0 ms, elapsed time = 1 ms.
Table '#RNT1'. Scan count 2, logical reads 57144, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 1594 ms, elapsed time = 1593 ms.
Как уже указывал @MadMyche, оба оператора используют полное сканирование таблиц, поскольку никаких индексов нет. Второй запрос выполняет сканирование дважды, что приводит к гораздо более высокому логическому вводу-выводу. Однако это снижение производительности компенсируется более эффективной агрегацией при присоединении.
Но, как было сказано в самом начале, самое главное, что вы получите правильные результаты, если существует несколько строк с одной и той же датой.