Sql Server Query Выбор Top и группировка по - PullRequest
1 голос
/ 14 ноября 2008

SpousesTable SpouseID

SpousePreviousAddressesTable PreviousAddressID , SpouseID , FromDate, AddressTypeID

Теперь у меня есть обновление самой последней для всей таблицы и присвоение самой новой независимо от SpouseID идентификатора AddressTypeID = 1

Я хочу назначить самый последний SpousePreviousAddress.AddressTypeID = 1 для каждого уникального SpouseID в таблице SpousePreviousAddresses.

UPDATE spa 
SET spa.AddressTypeID = 1
FROM SpousePreviousAddresses AS spa INNER JOIN Spouses ON spa.SpouseID = Spouses.SpouseID,
(SELECT TOP 1 SpousePreviousAddresses.* FROM SpousePreviousAddresses 
    INNER JOIN Spouses AS s ON SpousePreviousAddresses.SpouseID = s.SpouseID 
    WHERE SpousePreviousAddresses.CountryID = 181 ORDER BY SpousePreviousAddresses.FromDate DESC) as us
WHERE spa.PreviousAddressID = us.PreviousAddressID

Я думаю, что мне нужна группа, но мой sql не такой уж и горячий. Благодаря.

Работающее обновление

Я ошибался, когда нашел решение этой проблемы ранее. Ниже приведено решение, с которым я собираюсь

WITH result AS
(
    SELECT ROW_NUMBER() OVER (PARTITION BY SpouseID ORDER BY FromDate DESC) AS rowNumber, *
    FROM SpousePreviousAddresses
    WHERE CountryID = 181
)
UPDATE result
SET AddressTypeID = 1
FROM result WHERE rowNumber = 1

Ответы [ 3 ]

5 голосов
/ 15 ноября 2008

Предполагая, что вы используете SQLServer 2005 (основываясь на сообщении об ошибке, полученном в предыдущей попытке), вероятно, самый простой способ сделать это - использовать пару функций ROW_NUMBER () с выражением Common Table, я думаю, что это может делай то, что ищешь:

WITH result AS
(
SELECT 
    ROW_NUMBER() OVER (PARTITION BY SpouseID ORDER BY FromDate DESC) as rowNumber,
    * 
FROM 
    SpousePreviousAddresses
)
    UPDATE SpousePreviousAddresses
    SET
        AddressTypeID = 2
    FROM 
        SpousePreviousAddresses spa
            INNER JOIN result r ON spa.SpouseId = r.SpouseId
    WHERE r.rowNumber = 1
            AND spa.PreviousAddressID = r.PreviousAddressID
            AND spa.CountryID = 181

В SQLServer2005 функция ROW_NUMBER () является одной из самых мощных. Это очень полезно во многих ситуациях. Время, потраченное на его изучение, будет многократно окуплено.

CTE используется для простоты кода abit, поскольку устраняет необходимость во временной таблице какого-либо вида для хранения промежуточного результата.

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

1 голос
/ 15 ноября 2008

Вот один из способов сделать это:

UPDATE spa1
SET spa1.AddressTypeID = 1
FROM SpousePreviousAddresses AS spa1 
  LEFT OUTER JOIN SpousePreviousAddresses AS spa2
    ON (spa1.SpouseID = spa2.SpouseID AND spa1.FromDate < spa2.FromDate)
WHERE spa1.CountryID = 181 AND spa2.SpouseID IS NULL;

Другими словами, обновите строку spa1, для которой не существует другой строки spa2 с таким же супругом и более поздней (более поздней) датой.

Существует ровно одна строка для каждого значения SpouseID, которое имеет наибольшую дату по сравнению со всеми другими строками (если есть) с таким же SpouseID.

Нет необходимости использовать GROUP BY, потому что существует неявная группировка, выполняемая соединением.

обновление: Я думаю, вы неправильно поняли цель OUTER JOIN. Если нет строки spa2, которая соответствует всем условиям соединения, тогда все столбцы spa2.* возвращаются как NULL. Вот как работают внешние соединения. Таким образом, вы можете искать случаи, когда spa1 не имеет подходящей строки spa2, проверяя, что spa2.SpouseID IS NULL.

0 голосов
/ 14 ноября 2008
UPDATE spa SET spa.AddressTypeID = 1 
     WHERE spa.SpouseID IN (
         SELECT DISTINCT s1.SpouseID FROM Spa S1, SpousePreviousAddresses S2
              WHERE s1.SpouseID = s2.SpouseID 
                  AND s2.CountryID = 181 
                  AND s1.PreviousAddressId = s2.PreviousAddressId
              ORDER BY S2.FromDate DESC)

Просто предположение.

...