Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/77.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
TSQL按键分组选择最近的非未来日期范围_Sql_Sql Server_Sql Server 2008_Tsql - Fatal编程技术网

TSQL按键分组选择最近的非未来日期范围

TSQL按键分组选择最近的非未来日期范围,sql,sql-server,sql-server-2008,tsql,Sql,Sql Server,Sql Server 2008,Tsql,以下是简化的价格表结构: 此价格表存储所有产品的所有价格。FromDate和ToDate列指定价格应生效的期间。如果指定日期没有促销活动,则返回为1900-01-01的空日期为默认价格 给定SKU和日期,查询应返回适用于该日期的产品价格。例如,选择using 2012-06-16应返回: 选择使用2012-06-15应返回: SQL server是MS SQL 2008 R2。我已经有一段时间没有编写上一个SQL查询了,我似乎无法理解这一点 任何帮助都将不胜感激。以下是我到目前为止的想法: se

以下是简化的价格表结构:

此价格表存储所有产品的所有价格。FromDate和ToDate列指定价格应生效的期间。如果指定日期没有促销活动,则返回为1900-01-01的空日期为默认价格

给定SKU和日期,查询应返回适用于该日期的产品价格。例如,选择using 2012-06-16应返回:

选择使用2012-06-15应返回:

SQL server是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

我认为某个地方应该有一个GroupBy,但是使用一个在失败时不返回错误消息的web服务并没有多大帮助:

您不需要GroupBy,只需要对日期添加一个限制:

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,等等。

您不需要分组人,只需对日期添加限制:

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等。

示例数据:

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和价格类型,我们对备用行和日期匹配行(如果有)都感兴趣 我们希望选择一个日期匹配行,因此,如果后备行前面有一个日期匹配行,则使用具有适当分区和ORDER BY子句的row_NUMBER对该日期匹配行进行排序 这是内部的原始查询 然后,我们只从Raw中选择行数为1的所有行。这将是存在的日期匹配行,或者是没有日期匹配行的回退行。 样本数据:

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和价格类型,我们对备用行和日期匹配行(如果有)都感兴趣 我们希望选择一个日期匹配行,因此,如果后备行前面有一个日期匹配行,则使用具有适当分区和ORDER BY子句的row_NUMBER对该日期匹配行进行排序 这是内部的原始查询 然后,我们只从Raw中选择行数为1的所有行。这将是存在的日期匹配行,或者是没有日期匹配行的回退行。
尽管您的第二个查询似乎有问题,但您忽略了价格为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 FIDLE:

尽管您的第二个查询似乎有问题,但您忽略了价格为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 FIDLE:

如果数据模型不同,这会更容易:例如,正如第一个想法,默认价格应该在一个完全不同的表中。无论如何,这仍然是可行的…为什么第二个查询忽略了价格为749的记录。我认为您希望处理1900-01-01日期,例如未指定的空日期,并始终添加这些日期。如果数据模型不同,这将更容易:例如,正如第一个想法,默认价格应位于完全不同的表中。无论如何,这仍然是可行的…为什么第二个查询忽略了价格为749的记录。我认为您希望处理1900-01-01日期,如未指定的空日期,并始终添加这些日期。这将为两行提供日期匹配,并为具有日期匹配行的PriceTypes提供回退。@AakashM似乎这就是您的意图!这将为两行提供日期匹配,并为具有日期匹配行的PriceTypes提供回退。@AakashM这似乎是我们的初衷!投票支持sqlfiddle,以前从未知道过。在第二个查询中不返回1900-01-01条目是我提问时的初衷,因为我只需要查询返回给定当前日期要显示的价格,但仍然返回1900-01-01价格对管理层可能有用,感谢您的回答。sqlfiddle的Upvoting,以前从未知道过。在第二次查询中不返回1900-01-01条目是我提问时的初衷,因为我只需要查询返回给定当前日期显示的价格,但仍然返回1900-01-01价格对管理非常有用,感谢您的回答。谢谢AakashM!这正是问题中提出的问题,并提供了详细的解释,帮助读者了解查询中发生了什么。谢谢AakashM!这正是问题中提出的问题,并提供了详细的解释,以帮助读者了解查询中发生了什么。