Получение последней записи, сгруппированной по идентификатору - PullRequest
0 голосов
/ 16 января 2019

У меня есть стол с запасом для продуктов. Проблема заключается в том, что каждый раз, когда происходит изменение запаса, новое значение сохраняется вместе с новым количеством. Пример:

ProductID | Quantity | LastUpdate
1           123        2019.01.01
2           234        2019.01.01
1           444        2019.01.02
2           222        2019.01.02

Поэтому мне нужно получить последнее обновление для каждого продукта и вернуть это:

ProductID | Quantity
1           444
2           222     

Следующий SQL работает, но медленно.

SELECT ProductID, Quantity
FROM (
    SELECT ProductID, Quantity
    FROM Stock
    WHERE LastUpdate 
    IN (SELECT MAX(LastUpdate) FROM Stock GROUP BY ProductID)
) 

Поскольку запрос медленный и предполагается, что его оставляют объединенным с другим запросом, я действительно хотел бы получить некоторую информацию о том, как сделать это лучше.

Есть ли другой способ?

Ответы [ 4 ]

0 голосов
/ 16 января 2019

Просто еще один вариант - использовать WITH TIES совместно с Row_Number()

Полное раскрытие информации: Ответ Вамси будет чуть более продуктивным.

Пример

Select Top 1 with ties * 
 From  YourTable
 Order by Row_Number() over (Partition By ProductID Order by LastUpdate Desc)

Возвращает

ProductID   Quantity    LastUpdate
1           444         2019-01-02
2           222         2019-01-02
0 голосов
/ 16 января 2019

Функция row_number () может быть наиболее эффективной, но большое замедление в вашем запросе заключается в использовании оператора IN при использовании в подзапросе, он немного сложнее, но объединение происходит быстрее. Этот запрос должен получить то, что вы хотите, и быть намного быстрее.

SELECT 
     a.ProductID
    ,a.Quantity 
FROM stock as a 
INNER JOIN (
            SELECT 
                 ProductID
                ,MAX(LastUpdate) as LastUpdate
            FROM stock 
            GROUP BY ProductID  
            ) b 
ON  a.ProductID = b.ProductId AND 
    a.LastUpdate = b.LastUpdate
0 голосов
/ 16 января 2019

Таким образом, вы можете использовать CTE (общее табличное выражение)

Базовые данные:

SELECT  1 AS ProductID
       ,123 AS Quantity
       ,'2019-01-01' as LastUpdate
INTO #table
UNION 
SELECT  2 AS ProductID
       ,234 AS Quantity
       ,'2019-01-01' as LastUpdate
UNION
SELECT  1 AS ProductID
       ,444 AS Quantity
       ,'2019-01-02' as LastUpdate
UNION
SELECT  2 AS ProductID
       ,222 AS Quantity
       ,'2019-01-02' as LastUpdate

Вот код, использующий общее табличное выражение.

WITH CTE (ProductID, Quantity, LastUpdate, Rnk)
AS
 (
 SELECT  ProductID
        ,Quantity
        ,LastUpdate
        ,ROW_NUMBER() OVER(PARTITION BY ProductID ORDER BY LastUpdate DESC) AS Rnk
 FROM #table
 )
SELECT ProductID, Quantity, LastUpdate
FROM CTE
WHERE rnk = 1

Возвращает

enter image description here

Затем вы можете присоединиться к CTE за любым нужным столом.

0 голосов
/ 16 января 2019

Используйте аналитические функции. row_number может использоваться в этом случае.

SELECT ProductID, Quantity
FROM (SELECT ProductID, Quantity, row_number() over(partition by ProductID order by LstUpdte desc) as rnum
      FROM Stock
     ) s
WHERE RNUM = 1

Или с first_value.

SELECT DISTINCT ProductID, FIRST_VALUE(Quantity) OVER(partition by ProductID order by LstUpdte desc) as quantuity
FROM Stock
...