Sql Server查询选择Top和分组依据

时间:2008-11-14 20:43:09

标签: sql sql-server database-partitioning

SpousesTable SpouseID

SpousePreviousAddressesTable PreviousAddressID SpouseID ,FromDate,AddressTypeID

我现在所拥有的是更新整个表格的最新版本并分配最新版本而不管SpouseID的AddressTypeID = 1

我想分配最新的SpousePreviousAddress.AddressTypeID = 1 对于SpousePreviousAddresses表中的每个唯一SpouseID。

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 个答案:

答案 0 :(得分:5)

假设您正在使用SQLServer 2005(基于您从上一次尝试中获得的错误消息),可能最直接的方法是将ROW_NUMBER()函数与公用表表达式一起使用,我想这可能是做你想要的:

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,因为它不需要某种临时表来存储itermediate结果。

生成的查询应该快速有效。我知道CTE中的select使用*,这有点过分,因为我们不需要所有列,但如果有人想看看查询中发生了什么,它可能有助于显示正在发生的事情。

答案 1 :(得分:1)

这是一种方法:

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的情况。

答案 2 :(得分:0)

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)

只是一个猜测。