2015-07-04 2 views
1

Я использую SQL Server 2014. У меня есть 3 таблицы в моей базе данных, которые должны быть объединены в запросе, и они заключаются в следующем:запросов для извлечения значений, соответствующих последней даты

ResStayDate.dbo

ResaID StayDate  Rate 
50  2015-01-20  235.00 
50  2015-01-21  235.00 
50  2015-01-22  235.00 
50  2015-01-23  235.00 
54  2015-02-10  200.00 
54  2015-02-11  200.00 
65  2015-03-12  155.00 
65  2015-03-13  155.00 
67  2015-04-10  290.00 
67  2015-04-11  290.00 
67  2015-04-12  290.00 

ResStay.dbo

ResaID Currency 
    50  USD 
    54  USD 
    65  EUR 
    67  EUR 

ExchangeRate.dbo

Currency  ExRate  EffectiveDate 
    USD  28.00  2015-01-20 
    EUR  40.00  2015-01-20 
    USD  30.00  2015-01-22 
    EUR  40.00  2015-01-22 
    USD  30.00  2015-03-13 
    EUR  40.00  2015-03-13 
    USD  30.00  2015-04-11 
    EUR  42.00  2015-04-11 

Вывод, который я хочу, чтобы мой запрос, чтобы дать следующим образом:

ResaID  StayDate Rate  ExRate  Revenue 
    50  2015-01-20 235.00  28.00   6580.00 
    50  2015-01-21 235.00  28.00   6580.00 
    50  2015-01-22 235.00  30.00   7050.00 
    50  2015-01-23 235.00  30.00   7050.00 
    54  2015-02-10 200.00  30.00   6000.00 
    54  2015-02-11 200.00  30.00   6000.00 
    65  2015-03-12 155.00  40.00   6200.00 
    65  2015-03-13 155.00  40.00   6200.00 
    67  2015-04-10 290.00  40.00   11600.00 
    67  2015-04-11 290.00  42.00   12180.00 
    67  2015-04-12 290.00  42.00   12180.00 

Доход рассчитывается следующим образом: ResStayDate.Rate * ExRate (путем сопоставления Currency в ResStay.dbo со значением Currency в ExchangeRate.dbo).

я прогрессировал далеко с моим запросом, но я застрял с тем, как соответствовать ResStayDate.StayDate с ExchangeRate.EffectiveDate так, что запрос может использовать правильный ExRate из Currency. Моя проблема заключается в том, что таблица ExchangeRate не перечисляет значения валюты ежедневно, но только при изменении ExRateCurrency.

Таким образом, ExRateCurrency действует до даты следующего изменения и так далее. Мне нужно сопоставить мой StayDate в таблице ResStayDate с соответствующим значением ExRate этого Currency в таблице ExchangeRate.

Итак, мой проект запрос, как в настоящее время выглядит следующим образом:

SELECT * FROM 

(
(SELECT ResaID, 
     StayDate, 
     Rate, 
     (?????) As [Revenue] 
FROM ResStayDate)a 

LEFT JOIN ResStay b ON b.ResaID = a.ResaID 
LEFT JOIN ExRate c ON c.Currency = b.Currency 

)xy 

Я не могу понять, как включить в ExRate в запросе, так что я могу использовать уравнение, чтобы получить Revenue колонки ,

ответ

2

Я хотел бы использовать CROSS APPLY здесь. Адрес SQL Fiddle.

Добавить индекс в ExchangeRate по телефону (Currency, EffectiveDate) и будет эффективным.

Убедитесь, что у вас есть значение в ExchangeRate для каждой валюты с EffectiveDate до первой даты в ResStayDate, в противном случае эти сроки не получит каких-либо соответствующих строк в CROSS APPLY, и они не будут появляться в конечном итоге. Если ваши данные могут иметь исторические значения, которые не имеют обменных курсов, используйте OUTER APPLY вместо CROSS APPLY. В этом случае вы получите NULL, и вы, по крайней мере, увидите, что что-то не так, вместо того, чтобы молча иметь строки в результате.

SELECT 
    ResStayDate.ResaID 
    ,ResStayDate.StayDate 
    ,ResStayDate.Rate 
    ,CA.ExRate 
    ,ResStayDate.Rate * CA.ExRate AS Revenue 
FROM 
    ResStayDate 
    INNER JOIN ResStay ON ResStay.ResaID = ResStayDate.ResaID 
    CROSS APPLY 
    (
     SELECT TOP(1) ExchangeRate.ExRate 
     FROM ExchangeRate 
     WHERE 
     ExchangeRate.Currency = ResStay.Currency 
     AND ExchangeRate.EffectiveDate <= ResStayDate.StayDate 
     ORDER BY ExchangeRate.EffectiveDate DESC 
) AS CA 
ORDER BY ResaID, StayDate; 
+0

Ничего себе! Это круто! Только то, что я хотел. Большое спасибо!. – user3115933

+0

Спасибо также за совет OUTER APPLY!Действительно, я получил NULL для определенной валюты под названием «MUR», на которую никогда не влияет изменение, поскольку оно всегда остается равным 1,00 (и, следовательно, не отображается в таблице ExchangeRate). Есть ли способ справиться с этим делом? Может быть с заявлением CASE? Благодарен, если вы можете оказать некоторую помощь. – user3115933

+0

Да, вы можете использовать 'OUTER APPLY' вместо' CROSS APPLY', а затем просто использовать 'ISNULL (CA.ExRate, 1)' вместо 'CA.ExRate'. Это делает все случаи, когда обменный курс недоступен по какой-либо причине, чтобы заставить ставку быть равной 1. Но, лично, я бы не поставил такой код в производство. Если данные недоступны, это означает, что их нужно проверять и вводить, вместо того, чтобы молча предполагать что-то. В случае, о котором вы упомянули, я бы добавил одну строку в «ExchangeRate» с «Currency =« MUR »,« ExRate = 1.0 »,« EffectiveDate = »2000-01-01'' или' 1900-01-01'. –

0

Почему вы не можете сделать, как показано ниже, а также использовать функцию ISNULL()

SELECT a.ResaID, 
     a.StayDate, 
     a.Rate, 
     a.Rate * ISNULL(c.ExRate,0) As [Revenue] 
FROM ResStayDate a 
LEFT JOIN ResStay b ON b.ResaID = a.ResaID 
LEFT JOIN ExchangeRate c ON c.Currency = b.Currency; 
Смежные вопросы