如何使用SQL返回指定日期或最近日期的值<指定日期?

时间:2011-03-21 02:36:48

标签: sql sql-server-2005

我写了一个SQL语句,根据日期参数返回价格列表,但我发现在某些日期,价格丢失了。我正在寻找一种方法来修改此声明以返回指定日期的价格,但如果不可用,则返回指定日期之前可用的最新价格的价格。

Select date, grp, id, price
From
  price_table
Where
  date In ('12/31/2009', '11/30/2009') And
  grp In ('Group1')

例如,我希望能够重新编写上面的语句以返回下面的所有记录,显示所有记录的相应参数日期。假设这是具有每日价格的表的子集,下面的值是所述月份的最后价格。

12/31/2009 Group1 1111 100
12/31/2009 Group1 2222 99
12/29/2009 Group1 3333 98
11/30/2009 Group1 1111 100
11/28/2009 Group1 2222 99
11/30/2009 Group1 3333 98

更新 感谢下面srgerg的一些帮助,我已经能够创建一个一次适用于一个日期的语句,但我仍然希望找到一种方法将多个日期传递给查询。

Select p1.date, p1.grp, p1.id, p1.price
From
  price_table As p1 Inner Join
  (Select Max(p2.date) As maxdt, id
    From
      price_table As p2
    Where
      p2.date <= '12/31/2009'
    Group By
      p2.id) As p On p.maxdt = p1.date And p1.id = p.id
Where grp in ('Group1')

2 个答案:

答案 0 :(得分:2)

您可以尝试这样的事情:

SELECT date, grp, id
    , (SELECT TOP 1 price
       FROM price_table P2
       WHERE P1.id = P2.id
       AND P1.grp = P2.grp
       AND P2.date <= P1.date
       ORDER BY P2.date DESC)
FROM price_table P1
WHERE P1.date IN ('12/31/2009', '11/30/2009')
AND P1.grp IN ('Group1')

修改要获取每个月,组和ID的最后一条记录,您可以尝试这样做:

SELECT date, grp, id, price
FROM price_table P1
WHERE P1.date = (SELECT MAX(date)
                 FROM price_table P2
                 WHERE P1.grp = P2.grp
                 AND P1.id = P2.id
                 AND YEAR(P1.date) = YEAR(P2.date)
                 AND MONTH(P1.date) = MONTH(P2.date))
AND P1.grp In ('Group1')

答案 1 :(得分:1)

这是我解决这个问题的方法:

  1. 将每个搜索日期与表格中的日期相关联。
  2. 将搜索日期用作(附加)组条款。
  3. 按降序排列日期,按组条款对其进行分区。
  4. 选择具有所需组字词值和rank = 1的内容。
  5. 剧本:

    WITH price_grouped AS (
      SELECT
        date, grp, id, price,
        dategrp = CASE
          WHEN date <= '11/30/2009' THEN '11/30/2009'
          WHEN date <= '12/31/2009' THEN '12/31/2009'
          /* extend the list of dates here */
        END
      FROM price_table
    ),
    price_ranked AS (
      SELECT
        date, grp, id, price, dategrp,
        rank = RANK() OVER (PARTITION BY grp, dategrp ORDER BY date DESC)
      FROM price_grouped
    )
    SELECT date, grp, id, price
    FROM price_ranked
    WHERE grp IN ('Group1')
      AND rank = 1
    

    上述解决方案可能看起来不太方便,因为必须重复每次搜索日期两次。另一种方法可能是将搜索日期列表定义为单独的CTE,并相应地以不同的方式分配日期:

    WITH search_dates (Date) AS (
      SELECT '11/30/2009' UNION ALL
      SELECT '12/31/2009'
      /* extend the list of dates here */
    ),
    price_grouped AS (
      SELECT
        p.date, p.grp, p.id, p.price,
        dategrp = MIN(d.Date)
      FROM price_table p
        INNER JOIN search_dates d ON p.date <= d.Date
      GROUP BY
        p.date, p.grp, p.id, p.price
    ),
    price_ranked AS (
      SELECT
        date, grp, id, price, dategrp,
        rank = RANK() OVER (PARTITION BY grp, dategrp ORDER BY date DESC)
      FROM price_grouped
    )
    SELECT date, grp, id, price
    FROM price_ranked
    WHERE grp IN ('Group1')
      AND rank = 1
    

    但考虑到前一种解决方案很可能更具性能。