2010-04-12 42 views
1

我有簡化爲這樣的產品表:視圖來選擇特定時間段或最遲當空

create table product(id int primary key identity, productid int, year int, quarter int, price money) 

和一些樣本數據:

insert into product select 11, 2010, 1, 1.11 
insert into product select 11, 2010, 2, 2.11 
insert into product select 11, 2010, 3, 3.11 
insert into product select 12, 2010, 1, 1.12 
insert into product select 12, 2010, 2, 2.12 
insert into product select 13, 2010, 1, 1.13 

價格是可以每個季度改變,但並非所有產品每季度都會獲得新的價格。現在我可以每季度複製數據,保持價格不變,但我寧願使用視圖。

如何創建可用於返回(例如)第2季度價格的視圖?我寫這個返回當前(=最新)價格:

CREATE VIEW vwCurrentPrices AS 
    SELECT * 
    FROM 
    (
     SELECT *, ROW_NUMBER() OVER (PARTITION BY productid ORDER BY year DESC, quarter DESC) AS Ranking   
     FROM product 
    ) p 
    WHERE p.Ranking = 1 

我想創建一個視圖,以便我可以使用查詢,如select * from vwProduct where quarter = 2

回答

1
CREATE TABLE quarters ([year] int, [quarter] int, PRIMARY KEY([year],[quarter])) 

INSERT INTO quarters ([year], [quarter]) 
SELECT 2000 + number/4 [year], number%4 + 1 [quarter] 
FROM master.dbo.spt_values 
WHERE type = 'P' AND number BETWEEN 0 and 199 

CREATE VIEW pricing WITH SCHEMABINDING AS 
WITH pricerank AS 
    (SELECT q.[year], q.[quarter], p.productid, p.price, 
    p.[year] effectiveyear, p.[quarter] effectivequarter, 
    ROW_NUMBER() OVER (PARTITION BY p.productid, 
    q.[year], q.[quarter] ORDER BY p.[year] DESC, p.[quarter] DESC) AS ranking 
    FROM dbo.quarters q INNER JOIN dbo.product p 
    ON p.[year] = q.[year] AND p.[quarter] <= q.[quarter] OR p.[year] < q.[year] 
    WHERE q.[year] <= YEAR(GETDATE())) 
SELECT [year], [quarter], productid, price 
FROM pricerank 
WHERE ranking = 1 

CREATE UNIQUE CLUSTERED INDEX IX_pricing ON pricing([year],[quarter],productid) 
+0

很不錯的!按預期工作。謝謝 – edosoft 2010-04-13 08:59:29

+0

恐怕這個觀點表現不佳。大約8.000個產品平均有3個數據週期需要大約30秒來選擇所有記錄。我發佈的UDF需要1s – edosoft 2010-04-13 18:14:45

+1

我已經使用永久[quarters]表進一步優化了代碼。您也可以嘗試在產品上添加索引([年],[季度])。 – 2010-04-14 06:57:28

0

一些嘗試後,我想出了一個UDF這完成了我期望的結果。它首先在所需日期(季度+年)之前過濾所有價格,然後採用最高的排名,即最新的結果。

CREATE FUNCTION dbo.fTest(@year int, @quarter int) 
RETURNS TABLE 
AS 

return 
(
    select * from 
    (
     SELECT *, 
     ROW_NUMBER() OVER (PARTITION BY productid ORDER BY year DESC, quarter DESC) AS rownum 
     FROM product 
     where DateAdd(month, (quarter - 1) * 3, DateAdd(Year, year - 1900, 0)) <= DateAdd(month, (@quarter - 1) * 3, DateAdd(Year, @year - 1900, 0)) 
    ) p 
    where rownum = 1 
) 
相關問題