1

这是简化的表结构PRICES

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 服务不是很有帮助:(

4

3 回答 3

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()with 合适的PARTITIONandORDER BY子句将日期匹配的行(如果有的话)排在后备行的前面
  • 这是内部, Raw, 查询
  • 然后,我们只需从中选择所有Raw具有 rownumber的行1。这将是它们存在的日期匹配行,或者是没有日期匹配行的后备行。
于 2012-06-19T10:15:57.397 回答
2

尽管您的第二个查询似乎有问题(尽管日期为 749,但您已省略了价格为 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

于 2012-06-19T10:19:15.363 回答
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 等。

于 2012-06-19T10:06:18.370 回答