我在MS SQL 2005/2008数据库中有这个SQL QUERY,它可以获得Money Money,Money Currency,Money Time和Currency Converter。我离开时加入了Table,它每天都收集波兰国家银行关于货币转换器的信息。
以下是查询:
SELECT t1.[TransakcjeGotowkoweKwota],
t1.TypyWaluty,
t1.[TransakcjeGotowkoweData],
t2.[kurs_sredni]
FROM [BazaZarzadzanie].[dbo].[TransakcjeGotowkowe] t1
LEFT JOIN [BazaZarzadzanie].[dbo].[KursyWalutNBP] t2
ON t1.TypyWaluty = t2.[kod waluty] AND t2.[data publikacji] = t1.[TransakcjeGotowkoweData]
WHERE [TypyWaluty] = 'EUR'
这是输出:
TransakcjeGotowkoweKwota TypyWaluty TransakcjeGotowkoweData kurs_sredni
-14153.04000000 EUR 2009-01-05 00:00:00.000 4,1137
-18.36000000 EUR 2009-07-01 00:00:00.000 4,4157
4.61000000 EUR 2007-09-30 00:00:00.000 NULL
55.50000000 EUR 2007-09-30 00:00:00.000 NULL
问题在于Kurs_sredni的NULL值。当在[KursyWalutNBP]中找不到[kurs_sredni]时,会发生这种情况。我想要实现的是当它发生时它应该得到最近的可能日期并获得当天的价值。
例如:
如果[Kurs Sredni]对于2007-09-30日期的值为NULL,它应该从2007-10-01获得值(如果它有一个当然)。
我该如何接受这个?
关于,
MadBoy
答案 0 :(得分:1)
我个人会转移到这种类型的用户定义函数,而不是连接。这样您就可以完全控制评估过程。您可以根据您的笔记以下列方式进行操作。
SELECT TOP 1 kurs_sredni
FROM YourTable
WHERE (Your Comparison here)
ORDER BY Date
这样,您可以在日期进行> =比较,如果它不存在,您将获得下一个最新的日期值。
答案 1 :(得分:1)
我不能尝试使用MS SQL,但这样的事情应该适合你。
它应该返回具有最小日期差异的值(如果可能,则返回相同的日期)。
SELECT * FROM (
SELECT t1.[TransakcjeGotowkoweKwota],
t1.TypyWaluty,
t2.[kurs_sredni],
ROW_NUMBER() OVER( PARTITION BY t1.[TransakcjeGotowkoweData] ORDER BY ABS(cast(t1.[TransakcjeGotowkoweData] - t2.[data publikacji] AS FLOAT)) ) rank
FROM [BazaZarzadzanie].[dbo].[TransakcjeGotowkowe] t1
LEFT JOIN [BazaZarzadzanie].[dbo].[KursyWalutNBP] t2
ON t1.TypyWaluty = t2.[kod waluty]
WHERE [TypyWaluty] = 'EUR'
) x
WHERE rank = 1
答案 2 :(得分:1)
helper table of dates对此有用;加入KursyWalutNBP,您可以轻松计算出每个日期的正确汇率。我将此作为一个视图,使最终查询更简单:
CREATE VIEW CurrencyNearRates (kod_waluty, data, kurs_sredni)
AS
SELECT currencydates.kod_waluty, currencydates.data, ratenow.kurs_sredni FROM (SELECT currencies.kod_waluty, Helper_Dates.data FROM currencies CROSS JOIN Helper_Dates) currencydates
LEFT OUTER JOIN KursyWalutNBP ratenow
ON
currencydates.kod_waluty = ratenow.kod_waluty
AND currencydates.data <= ratenow.data_publikacji
AND ratenow.data_publikacji =
(
SELECT MIN(futurerates.data_publikacji)
FROM KursyWalutNBP futurerates
WHERE ratenow.kod_waluty = futurerates.kod_waluty
AND currencydates.data <= futurerates.data_publikacji
)
这会为您提供如下数据:
SELECT * FROM CurrencyNearRates ORDER BY kod_waluty, data;
|kod_waluty |data |kurs_sredni|
|----------------------------------------|
|EUR |2009-01-04 |4.1137 |
|EUR |2009-01-05 |4.1137 |
|EUR |2009-01-06 |4.4157 |
|EUR |2009-01-07 |4.4157 |
----------------------------------------
然后,您只需在TransakcjeGotowkowe中的交易和CurrencyNearRates中的汇率之间进行简单的连接:
SELECT
t1.[TransakcjeGotowkoweKwota],
t1.[TypyWaluty],
t1.[TransakcjeGotowkoweData],
CurrencyNearRates.[kurs_sredni]
FROM
dbo.[TransakcjeGotowkowe] t1
LEFT OUTER JOIN CurrencyNearRates
ON t1.[TypyWaluty] = CurrencyNearRates.[kod_waluty]
AND t1.[TransakcjeGotowkoweData] = CurrencyNearRates.[data]
WHERE t1.[TypyWaluty] = 'EUR'
ORDER BY t1.[TransakcjeGotowkoweData]
这会给你这样的输出:
|TransakcjeGotowkoweKwota |TypyWaluty |TransakcjeGotowkoweData |kurs_sredni |
|-----------------------------------------------------------------------------------|
|-18.36 |EUR |2009-07-01 |4.4157 |
|-14153.04 |EUR |2009-01-05 |4.1137 |
|4.61 |EUR |2007-09-30 |4.5678 |
|55.5 |EUR |2007-09-30 |4.5678 |
-----------------------------------------------------------------------------------
答案 3 :(得分:0)
我在理解您的查询时遇到了一些麻烦,但这是我认为您要解决的问题的一般解决方案。如果每个父母可能有很多孩子,那么您可能希望限制日期开始(例如,在LEFT OUTER JOIN和子查询中包含条件,以便它仅限于@my_date 3天内的子项(作为示例)至少那时日期的索引可能会有用,而下面的代码根本无法使用它。
SELECT
P.parent_id,
C.stuff
FROM
Parent P
LEFT OUTER JOIN Child C ON
C.parent_id = P.parent_id
WHERE
NOT EXISTS
(
SELECT
*
FROM
Child C2
WHERE
C2.parent_id = P.parent_id AND
ABS(DATEDIFF(ss, C2.my_date, @my_date)) < ABS(DATEDIFF(ss, C.my_date, @my_date))
)
答案 4 :(得分:0)
这样的事情应该这样做:
SELECT t1.[TransakcjeGotowkoweKwota],
t1.TypyWaluty,
t1.[TransakcjeGotowkoweData],
t2.[kurs_sredni]
FROM [BazaZarzadzanie].[dbo].[TransakcjeGotowkowe] t1
LEFT JOIN (
select ta.TypyWaluty, ta.[TransakcjeGotowkoweData], min(ABS(cast(ta.[TransakcjeGotowkoweData] - tb.[data publikacji] as float))) as ClosestDate
FROM [BazaZarzadzanie].[dbo].[TransakcjeGotowkowe] ta
inner join [BazaZarzadzanie].[dbo].[KursyWalutNBP] tb ON ta.TypyWaluty = tb.[kod waluty]
group by ta.TypyWaluty, ta.[TransakcjeGotowkoweData]
) t2c ON t1.TypyWaluty = t2c.TypyWaluty
AND t1.[TransakcjeGotowkoweData] = t2c.[TransakcjeGotowkoweData]
LEFT JOIN [BazaZarzadzanie].[dbo].[KursyWalutNBP] t2 ON t2c.TypyWaluty = t1.TypyWaluty
AND t1.[TransakcjeGotowkoweData] = t2.[TransakcjeGotowkoweData]
AND t2c.ClosestDate = ABS(cast(t1.[TransakcjeGotowkoweData] - t2.[data publikacji] as float))
WHERE t1.[TypyWaluty] = 'EUR'
答案 5 :(得分:0)
对此最好的答案是米切尔的一个。我已经创建了
CREATE FUNCTION KursWaluty
(
@typWaluty nvarchar(15),
@dataWaluty DATETIME
)
RETURNS varchar(30)
AS BEGIN
RETURN ( SELECT TOP 1
kurs_sredni
FROM [BazaZarzadzanie].[dbo].[KursyWalutNBP]
WHERE [kod waluty] = @typWaluty
AND [data publikacji] >= @dataWaluty
ORDER BY [data publikacji]
)
end
并使用此查询来获取它:
SELECT t1.[TransakcjeGotowkoweKwota],
TypyWaluty,
[TransakcjeGotowkoweData],
CASE WHEN [kurs_sredni] IS NULL
THEN BazaZarzadzanie.dbo.KursWaluty(TypyWaluty, [TransakcjeGotowkoweData])
ELSE [kurs_sredni]
END AS 'Currency'
FROM [BazaZarzadzanie].[dbo].[TransakcjeGotowkowe] t1
LEFT JOIN [BazaZarzadzanie].[dbo].[KlienciPortfeleKonta] t2
ON t1.[KlienciPortfeleKontaID] = t2.[KlienciPortfeleKontaID]
LEFT JOIN [BazaZarzadzanie].[dbo].[KursyWalutNBP]
ON TypyWaluty = [kod waluty]
AND [data publikacji] = [TransakcjeGotowkoweData]
WHERE [TypyWaluty] = 'EUR' -- AND [kurs_sredni] IS NULL
这很有效,似乎很快(2秒)。我使用AND [kurs_sredni] IS NULL来验证空值现在是否正确值。