Как вы можете использовать SQL для возврата значений за указанную дату или ближайшую дату <указанную дату? - PullRequest
0 голосов
/ 21 марта 2011

Я написал инструкцию SQL, чтобы вернуть список цен на основе параметра даты, но я обнаружил, что в некоторые даты цена отсутствует. Я ищу способ изменить это заявление, чтобы вернуть цену в указанную дату, но если она недоступна, верните цену для самой последней доступной цены до указанной даты.

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

Например, в I я хотел бы иметь возможность переписать приведенное выше утверждение, чтобы вернуть все записи ниже, показывая соответствующие даты параметров для всех записей. Предположим, что это подмножество таблицы с дневными ценами, а приведенные ниже значения являются последними ценами за отмеченные месяцы.

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

UPDATE: Благодаря некоторой помощи 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 ]

2 голосов
/ 21 марта 2011

Вы можете попробовать что-то вроде этого:

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')

Редактировать Чтобы получить последнюю запись за каждый месяц, группу и идентификатор, вы можете попробовать это:

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 голос
/ 21 марта 2011

Вот мой подход к решению этой проблемы:

  1. Свяжите каждую дату поиска с датой в таблице.
  2. Используйте даты поиска в качестве (дополнительных) групповых терминов.
  3. Ранжируйте даты в порядке убывания, разбивая их по групповым терминам.
  4. Выберите те, у которых есть нужные значения групповых терминов и rank = 1.

Сценарий:

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

Но учтите, что первое решение, скорее всего, будет более производительным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...