SQL查询按日期选择最多一个有效行w.r.t.外键

时间:2009-08-14 14:17:00

标签: sql-server-2005 tsql

我有一个表(SQL Server 2005),其中包含以下列:

State:
- StateId INT PRIMARY KEY
- VehicleId INT
- ValidFromDate DATETIME

对于每个VehicleId,此表中可以有多行。我想选择当前有效的状态(带有日期参数)。每辆车最多可以有一个有效状态(最小ValidFromDate小于日期参数的车辆。)

如果表格如下:

StateId  VehicleId  ValidFromDate
---      ---        ---
1        1          2009-01-01
2        1          2009-06-02
3        1          2009-11-03
4        2          2009-06-04
5        3          2009-10-05

@Date = '2009-08-14'我希望查询产生以下结果:

StateId  VehicleId  ValidFromDate
---      ---        ---
2        1          2009-06-02
4        2          2009-06-04

我认为以下查询会产生正确的结果:

SELECT * FROM State s1
WHERE s1.StateId IN (SELECT TOP 1 StateId 
                     FROM State s2
                     WHERE s2.ValidFromDate <= @Date AND s1.VehicleId = s2.VehicleId 
                     ORDER BY s2.ValidFromDate DESC, s2.StateId DESC)

但是必须有一种更好的方法来做到这一点,使用某种分组条款,对吧?使用同一个表的子查询感觉不对。

2 个答案:

答案 0 :(得分:1)

使用TOP 1的方式只返回一行,而不是所有可能的行。我相信你正在寻找的结果是这样的。

但它仍然使用子查询来获取MAX日期。我现在知道另一种方式。但是,我经常使用它,虽然速度不快,但我发现它并不太慢。

SELECT
    *
FROM
    State
WHERE
    State.ValidFromDate =
(
    SELECT
        MAX(ValidDromDate)
    FROM
        State2
    WHERE
        State2.VehicleId = State.VehicleId
    AND
        State2.ValidFromDate <= @Date
)

答案 1 :(得分:1)

您可以使用SQL 2005 RANK子句来帮助解决“按组排名前X”问题。

这样的查询可以解决您的问题。注意:我认为在给定数据的情况下,VehicleId应该是您预期结果集中的2。

SELECT dateranks.*
FROM
(
    select
    s1.StateId,
    s1.VehicleId,
    s1.ValidFromDate,
    RANK() OVER (PARTITION BY s1.VehicleId ORDER BY s1.ValidFromDate desc) AS 'DateRank'
    FROM [state] s1
    WHERE
    ValidFromDate <= '8/14/2009'
)
dateranks
where
    dateranks.ValidFromDate <= '8/14/2009'
    AND DateRank = 1

有用的链接: