按最新日期选择记录

时间:2014-02-20 13:03:30

标签: sql-server

我正在努力形成一个返回不同类型对象的最新记录的查询。我创建了以下示例,显示了我想要实现的目标。

表格

CREATE TABLE Fruit
(
    ID   [int] PRIMARY KEY IDENTITY (1,1) NOT NULL,
    Name [nvarchar](20) NOT NULL
)

CREATE TABLE Bites
(
    ID       [int] PRIMARY KEY IDENTITY (1,1) NOT NULL,
    FruitID  [int] FOREIGN KEY REFERENCES Fruit(ID) NOT NULL,
    BittenOn [datetime] NOT NULL
)

现在填充一些测试数据。

INSERT INTO Fruit VALUES ( 'Apple' );
INSERT INTO Fruit VALUES ( 'Orange' );
INSERT INTO Fruit VALUES ( 'Strawberry' );

INSERT INTO Bites VALUES ( 1, '2014/2/20 12:30:00' );
INSERT INTO Bites VALUES ( 2, '2014/2/20 12:31:00' );
INSERT INTO Bites VALUES ( 2, '2014/2/20 12:32:00' );
INSERT INTO Bites VALUES ( 3, '2014/2/20 12:33:00' );
INSERT INTO Bites VALUES ( 3, '2014/2/20 12:34:00' );
INSERT INTO Bites VALUES ( 3, '2014/2/20 12:35:00' );
INSERT INTO Bites VALUES ( 1, '2014/2/20 12:40:00' );
INSERT INTO Bites VALUES ( 3, '2014/2/20 12:40:00' );

我希望我的查询返回每个水果被咬的最新日期。 我尝试了以下方法:

SELECT
    F.Name,
    B.BittenOn as LastBittenOn
FROM
    Fruit as F
INNER JOIN
    Bites as B ON B.BittenOn = ( SELECT MAX(BittenOn) FROM Bites )AND B.FruitID=F.ID

但我只收到苹果和草莓,因为他们分享了最新的咬合日期,但我也希望Orange有日期/时间'2014 / 2/20 12:32:00'。

有人可以帮我处理所需的查询吗?

安迪

3 个答案:

答案 0 :(得分:1)

这样的东西
SELECT  f.Name,
        b.BittenOn
FROM    Fruit as F OUTER APPLY
        (
            SELECT  TOP 1 *
            FROM    Bites b
            WHERE   b.FruitID = f.ID
            ORDER BY b.BittenOn DESC
        ) b

另一种选择是

;WITH BitesCTE AS (
        SELECT  FruitID,
                MAX(BittenOn) BittenOn
        FROM    Bites
        GROUP BY    FruitID
)
SELECT  f.Name,
        b.BittenOn
FROM    Fruit f LEFT JOIN
        BitesCTE b  ON  f.ID = b.FruitID

答案 1 :(得分:0)

SELECT
    F.Name,
    B.BittenOn as LastBittenOn
FROM
    Fruit as F
INNER JOIN
    ( SELECT ROW_NUMBER()OVER(PARTITION BY FruitID ORDER BY BittenOn DESC) AS row_num
            ,FruitID
            ,BittenOn
    FROM Bites
    ) B
    ON F.ID = B.FruitID
    AND B.row_num = 1

答案 2 :(得分:0)

另一种选择是上述的旁观者答案:

SELECT  f.Name,
        b.BittenOn
FROM    Fruit as F OUTER APPLY
        (
            SELECT  MAX(b.BittenOn) as BittenOn
            FROM    Bites b
            WHERE   b.FruitID = f.ID
            GROUP BY b.FruitID
        ) b

根据索引,它可能会更快,因为它消除了昂贵的排序。当我运行原始版本和更改版本时,执行计划建议查询成本为14%对86%(相对于批处理),支持使用max()

编辑:另一个版本根据评论中的要求提供不同的输出:

SELECT LastBites.FruitID, Bites.ID 
FROM Bites
INNER JOIN (
    SELECT b.FruitID,  MAX(b.BittenOn) as BittenOn
    FROM Bites b
    GROUP BY b.FruitID
) LastBites ON Bites.BittenOn = LastBites.BittenOn AND Bites.FruitID = LastBites.FruitID
ORDER BY LastBites.FruitID ASC