Существует метод для нахождения строк с максимальными или минимальными значениями, который включает в себя СЛЕДУЮЩЕЕ СОЕДИНЕНИЕ к себе, а не более интуитивно понятное, но, возможно, и более дорогое, ВНУТРЕННЕЕ СОЕДИНЕНИЕ к составному списку, производному от себя.
В основном, метод использует этот шаблон:
SELECT t.*
FROM t
LEFT JOIN t AS t2 ON t.key = t2.key
AND t2.Value > t.Value /* ">" is when getting maximums; "<" is for minimums */
WHERE t2.key IS NULL
или его аналог НЕ СУЩЕСТВУЕТ:
SELECT *
FROM t
WHERE NOT EXISTS (
SELECT *
FROM t AS t2
WHERE t.key = t2.key
AND t2.Value > t.Value /* same as above applies to ">" here as well */
)
Итак, результатом являются все строки, для которых не существует строки с одинаковым ключом и значением, превышающим заданное.
Когда есть только одна таблица, применение описанного выше метода довольно просто. Однако, это может быть не так очевидно, как применять его, когда есть другая таблица, особенно когда, как и в вашем случае, другая таблица усложняет фактический запрос не только тем, что он там, но и предоставляя нам дополнительную фильтрацию. для значений, которые мы ищем, а именно с верхними пределами для дат.
Итак, вот как может выглядеть результирующий запрос при применении версии метода LEFT JOIN:
SELECT
d.TransactionID,
d.FundCode,
d.TransactionDate,
v.OfferPrice
FROM Transaction d
INNER JOIN Price v ON v.FundCode = d.FundCode
LEFT JOIN Price v2 ON v2.FundCode = v.FundCode /* this and */
AND v2.PriceDate > v.PriceDate /* this are where we are applying
the above method; */
AND v2.PriceDate < d.TransactionDate /* and this is where we are limiting
the maximum value */
WHERE v2.FundCode IS NULL
А вот аналогичное решение с NOT EXISTS:
SELECT
d.TransactionID,
d.FundCode,
d.TransactionDate,
v.OfferPrice
FROM Transaction d
INNER JOIN Price v ON v.FundCode = d.FundCode
WHERE NOT EXISTS (
SELECT *
FROM Price v2
WHERE v2.FundCode = v.FundCode /* this and */
AND v2.PriceDate > v.PriceDate /* this are where we are applying
the above method; */
AND v2.PriceDate < d.TransactionDate /* and this is where we are limiting
the maximum value */
)