2012-06-19 24 views
1

分組這裏是PRICES簡化表結構:TSQL選擇最接近的非將來的日期範圍內按鍵

SKU  PriceType FromDate  ToDate  Price 
.............................................................. 
SUR40 NONMEMBER 1900-01-01 1900-01-01 1000 
SUR40 RSP   1900-01-01 1900-01-01 1500 
SUR40 MEMBER  2012-07-04 2012-07-04 649 
SUR40 MEMBER  2012-06-15 2012-06-15 699 
SUR40 MEMBER  2012-06-01 2012-06-01 599 
SUR40 MEMBER  2012-03-31 2012-03-31 699 
SUR40 MEMBER  1900-01-01 1900-01-01 749 

PRICES表存儲了所有的所有產品的價格。 FromDateToDate列指定價格應該生效的時間段。如果在指定的日期沒有促銷,則空日期(以1900-01-01返回)是默認價格。

給定SKU和日期,查詢應返回適用於該日期的產品價格。例如,使用2012-06-16選擇應該返回:

SUR40 NONMEMBER 1900-01-01 1900-01-01 1000 
SUR40 RSP   1900-01-01 1900-01-01 1500 
SUR40 MEMBER  1900-01-01 1900-01-01 749 

使用2012-06-15應該返回選擇:

SUR40 NONMEMBER 1900-01-01 1900-01-01 1000 
SUR40 RSP   1900-01-01 1900-01-01 1500 
SUR40 MEMBER  2012-06-15 2012-06-15 699 

SQL服務器是MS SQL 2008 R2。我寫了最後一條SQL查詢已經有一段時間了,我似乎無法理解這一點。 :(

任何幫助將不勝感激下面是我想出迄今:

select SKU, PriceType, FromDate, ToDate, Price from PRICES 
where SKU IN ('SUR40') 
and PriceType IN ('NONMEMBER','RSP','MEMBER') 
and FromDate < GETDATE() 
order by PriceType, FromDate DESC 

我覺得應該有一個group by的地方,但沒有返回錯誤的web服務工作一旦失敗消息是不是非常有幫助:(

+1

這會更容易爲數據模型不同:)例如,正如第一的思想,*默認*價格應該是在一個完全不同的表。無論如何,這仍然是可行的...... – AakashM

+0

爲什麼第二個查詢忽略價格爲749的記錄。我以爲你想處理像空日期(未指定)'1900-01-01'日期,並添加這些總是。 –

回答

2

樣本數據:

DECLARE @PRICES TABLE (
    SKU nvarchar(10), 
    PriceType nvarchar(10), 
    FromDate date, 
    ToDate date, 
    Price int 
) 

INSERT @PRICES VALUES 
('SUR40' , 'NONMEMBER' , '1900-01-01' , '1900-01-01' , 1000) , 
('SUR40' , 'RSP'  , '1900-01-01' , '1900-01-01' , 1500) , 
('SUR40' , 'MEMBER' , '2012-07-04' , '2012-07-04' , 649 ) , 
('SUR40' , 'MEMBER' , '2012-06-15' , '2012-06-15' , 699 ) , 
('SUR40' , 'MEMBER' , '2012-06-01' , '2012-06-01' , 599 ) , 
('SUR40' , 'MEMBER' , '2012-03-31' , '2012-03-31' , 699 ) , 
('SUR40' , 'MEMBER'  , '1900-01-01' , '1900-01-01' , 749 ) 

查詢參數:

DECLARE @SKU nvarchar(10) 
DECLARE @Date date 

SET @SKU = 'SUR40' 
SET @Date = '2012-06-15' 

查詢:

SELECT * FROM 
    (
    SELECT 
     SKU, 
     PriceType, 
     FromDate, 
     ToDate, 
     Price, 
     ROW_NUMBER() 
      OVER (
       PARTITION BY SKU, PriceType 
       ORDER BY 
       CASE 
        WHEN (FromDate = '1900-01-01' 
         AND ToDate = '1900-01-01') THEN 1 
        ELSE 0 
       END ASC) rn 
    FROM @PRICES 
    WHERE 
     SKU = @SKU 
     AND (
      (FromDate = '1900-01-01' AND ToDate = '1900-01-01') 
      OR 
      (FromDate <= @Date AND @Date <= ToDate) 
      ) 
    ) Raw 
WHERE rn = 1 

說明從內到外:

  • 對於每個SKU和價格類型,我們感興趣的兩個備用行和日期匹配行中,如果有一個
  • 我們希望喜歡日期匹配行,所以我們使用ROW_NUMBER()用合適的PARTITIONORDER BY條款,訂購日期匹配的行(如果有的話),在回退行
  • 這是內在的,Raw前,查詢
  • 然後,我們只是從Raw有ROWNUMBER 1選擇所有的行。這將是它們存在的日期匹配行,或者沒有日期匹配行的後備行。
+0

謝謝AakashM!這正是問題中提出的問題,並提供了詳細的解釋來幫助讀者理解查詢中發生了什麼。 – Phil

0

你並不需要通過一組,你只需要一個限制添加到日期:

select SKU, PriceType, FromDate, ToDate, Price from PRICES 
where SKU IN ('SUR40') 
and PriceType IN ('NONMEMBER','RSP','MEMBER') 
and (FromDate = '1900-01-01' or @dateToProcess between FromDate and ToDate) 
order by PriceType, FromDate DESC 

@dateToProcess將2012-06-16 2012-06-15或等

+0

這將爲PriceTypes提供*兩行*(日期匹配和回退)以及日期匹配行。 – AakashM

+0

@AakashM這似乎是什麼意圖! –

2

雖然你的第二個查詢似乎是馬車(你省略同價位749的記錄雖然日期是`1900-01-01),我想你想返回總是1900-01-01日期:

select SKU, PriceType, FromDate, ToDate, Price 
from PRICES 
where SKU='SUR40' 
and PriceType IN ('NONMEMBER','RSP','MEMBER') 
and ((FromDate='1900-01-01' AND ToDate='1900-01-01') 
    OR 
    (FromDate>='2012-06-15' AND ToDate<='2012-06-15') 
    ) 
order by PriceType, FromDate DESC 

當然你應該使用上面的參數而不是常量值。

這裏的SQL小提琴:http://sqlfiddle.com/#!3/18cf7/4

+0

Upvoting for sqlfiddle,從來不知道它。當我問這個問題時,沒有返回第二個查詢中的1900-01-01條目,因爲我只需要查詢返回給定當前日期的顯示價格,但仍然返回'1900-01-01'價格反正可以是有用的管理,感謝您的答案。 – Phil