Регистрация на основе максимальной даты <= данной даты

У меня есть две таблицы, которые выглядят примерно так:

Таблица 1:

Unit      Date
A         9/30/17
B         9/30/17

Таблица 2:

Unit     Date      Metric
A        9/30/17   100
A        6/30/17   250
A        5/31/17   150
B        8/15/17   200
B        4/30/17   150
B        4/15/17   100

Для каждой комбинации Единицы и Даты из Таблицы 1 я хочу получить соответствующее значение Метрики из Таблицы 2. Если в Таблице 2 нет совпадений, я хочу отозвать значение Метрики для следующей ближайшей даты, которая < дата из таблицы 1. Используя приведенные выше примеры, я ожидаю получить 100 для блока A и 200 для блока B.

Как я могу получить это в форме запроса? Мне было трудно оборачиваться вокруг него. Было бы легко, если бы я имел дело только с датами, но компонент Unit - это то, что меня отталкивает.

1 ответ

Получить точное совпадение относительно просто, используя левое соединение

SELECT t1.Unit, t2.Metric
FROM Table1 t1 
LEFT JOIN Table2 t2 ON t2.Unit = t1.Unit AND t2.Date = t1.Date

С этим запросом t2.Metric будет NULL, если нет точного соответствия. Получить метрику без точного соответствия сложнее. В MS SQL Server вы могли бы написать пользовательскую функцию (UDF), чтобы вернуть ближайшее значение.

create function dbo.udfGetMetric(@Unit char(1), @Date datetime) returns int
as 
BEGIN
declare @Metric smallint;
SELECT TOP(1) @Metric = Metric
FROM Table2 
WHERE Unit = @Unit
    and [Date] < @Date
ORDER BY [Date] DESC;

RETURN @Metric;
END
GO

Затем вы можете вызвать эту функцию в своем запросе, когда значение равно NULL.

SELECT t1.Unit, ISNULL(t2.Metric, dbo.udfGetMetric(t1.Unit, t1.[Date])) as Metric
FROM Table1 t1 
LEFT JOIN Table2 t2 ON t2.Unit = t1.Unit AND t2.[Date] = t1.[Date];

Вы можете сделать то же самое, используя подзапрос вместо функции:

SELECT t1.Unit
, ISNULL(t2.Metric, (SELECT TOP(1) Metric
                    FROM Table2 
                    WHERE Unit = t1.Unit
                        and [Date] < t1.[Date]
                    ORDER BY [Date] DESC)) as Metric
FROM Table1 t1 
LEFT JOIN Table2 t2 ON t2.Unit = t1.Unit AND t2.[Date] = t1.[Date];
Другие вопросы по тегам