想象一下MS SQL Server表中名为"tblPrices"的金融交易和报价数据。
SeqNo Ticker TradeType JulianTime Price BidPrice AskPrice
1 CLK4 Quote 735706.11 NULL 103 NULL
2 CLK4 Quote 735706.59 NULL NULL 105
3 CLK4 Trade 735706.59 103 NULL NULL
NULL用于节省表中的空间。在提取值为"Trade"的"TradeType"数据时,我还想提取最近的数据'BidPrice'和'AskPrice',根据JulianTime不为NULL。
ie。上面的SeqNo 3的输出可以是:
JulianTime TradeType Price BidPrice AskPrice
735706.59 Trade 103 103 105
注:SeqNo是一个步长为1的恒等式。JulianTime是MATLAB发明的DateTime的数值。
我该怎么做?
SELECT Ticker,
Min(CASE
WHEN TradeType = 'Trade'
AND Price IS NOT NULL THEN JulianTime
END),
Min(Price),
Min(BidPrice),
Max(AskPrice)
FROM tblPrices
GROUP BY Ticker
WITH cte
AS (SELECT ticker,
juliantime,
tradetype,
price
FROM tblprices
WHERE tradetype = 'Trade')
SELECT cte.ticker,
cte.juliantime,
cte.tradetype,
cte.price,
bid.bidprice,
ask.askprice
FROM cte
OUTER apply (SELECT TOP 1 t1.bidprice
FROM tblprices t1
WHERE t1.ticker = cte.ticker
AND t1.bidprice IS NOT NULL
AND t1.juliantime <= cte.juliantime
ORDER BY t1.juliantime DESC) bid
OUTER apply (SELECT TOP 1 t1.askprice
FROM tblprices t1
WHERE t1.ticker = cte.ticker
AND t1.askprice IS NOT NULL
AND t1.juliantime <= cte.juliantime
ORDER BY t1.juliantime DESC) ask
你有一个误解- NULL值消耗更多的空间和更多的CPU比不允许NULL的等效设计。每个标记都记录了一个操作,该操作仅是BID、ASK和SALE中的一个,因此合适的表设计是
CREATE TABLE tblPrices(
ID int identity not null primary key
,Ticker varchar(10) not null references tblTicker(Code)
,TradeType char(3) not null -- must be one of BID, ASK, SLD
,JulianTime datetime not null
,Price money not null
)
使用这种表设计,查询变成
elect
JulianTime
,Price
,(select top 1 Price
from tblPrices bid
where bid.JulianTime < sld.JulianTime
and bid.Ticker = sld.Ticker
and bid.TradeType = 'BID'
order by JulianTime desc
) as BidPrice
,(select top 1 Price
from tblPrices bid
where bid.JulianTime < sld.JulianTime
and bid.Ticker = sld.Ticker
and bid.TradeType = 'ASK'
order by JulianTime desc
) as AskPrice
from tblPrices sld
where sld.TradeType = 'SLD';