简体   繁体   English

过滤具有最新“有效自”日期的重叠日期范围

[英]Filter overlapping date ranges with latest "Valid from" date

I have a table with price lists that specifies the price of an item in a country for a specific time period.我有一个价格表表,其中指定了特定时间段内某个国家/地区的商品价格。 The issue with my table is, that there are overlapping price lists for the same item in the same country.我的表格的问题是,同一国家/地区的同一商品有重叠的价目表。 What I wish, is to select the overlapping price list with the latest valid from date.我想要的是 select 具有最新有效起始日期的重叠价目表。 Looking at the picture below the highlighted rows would be the desired end-result out of the 7 example rows:查看下面突出显示的行的图片将是 7 个示例行中所需的最终结果:

在此处输入图像描述

Data sample:数据样本:

CREATE TABLE #PriceList
(
    [Country] VARCHAR(15),
    [Price list] VARCHAR(25),
    [Item number] INTEGER,
    [Price] DECIMAL(10, 2),
    [Valid from] INTEGER,
    [Valid to] INTEGER
);

INSERT INTO #PriceList
(
    Country,
    [Price list],
    [Item number],
    Price,
    [Valid from],
    [Valid to]
)
VALUES
('United Kingdom', 'Price list Tech', 33333, 20.50, 20200101, 20201231),
('United Kingdom', 'Price list Tech', 33333, 20.50, 20200102, 20201231),
('Germany', 'Price list stuff', 44444, 15.50, 20200102, 20201231),
('Germany', 'Price list stuff', 44444, 15.50, 20200101, 20200630),
('USA', 'Price list textile new', 55555, 32.25, 20200102, 20201231),
('USA', 'Price list textile', 55555, 32.50, 20200101, 20200630),
('Germany', 'Price list stuff', 44444, 15.50, 20210101, 20210630);

What I have tried:我试过的:

SELECT  Country,
       [Price list],
       [Item number],
       [Price],
       [Valid from],
       [Valid to]
       FROM(
SELECT Country,
       [Price list],
       [Item number],
       [Price],
       [Valid from],
       [Valid to],
       ROW_NUMBER() OVER (PARTITION BY a.Country,
                                       a.[Item number],
                                       a.[Valid to]
                          ORDER BY a.[Valid from] DESC
                         ) AS rn
FROM #PriceList a
) b
WHERE b.rn = 1

OUTPUT: OUTPUT:

在此处输入图像描述

As you can see there are still overlapping price lists.如您所见,仍然存在重叠的价目表。

If I remove "Valid to" in the partition by clause then row_number will eliminate too many price lists.如果我删除 partition by 子句中的“Valid to”,则 row_number 将删除太多价目表。 As you can see it eliminated two of Germany's price lists when it should only have eliminated the overlapping one.如您所见,它删除了德国的两个价目表,而本应只删除重叠的一个。 Without "Valid to", it strictly just checks for the latest "Valid from" date.没有“有效至”,它严格地只检查最新的“有效自”日期。

SELECT  Country,
       [Price list],
       [Item number],
       [Price],
       [Valid from],
       [Valid to]
       FROM(
SELECT Country,
       [Price list],
       [Item number],
       [Price],
       [Valid from],
       [Valid to],
       ROW_NUMBER() OVER (PARTITION BY a.Country,
                                       a.[Item number]
                          ORDER BY a.[Valid from] DESC
                         ) AS rn
FROM #PriceList a
) b
WHERE b.rn = 1

在此处输入图像描述

All help, tips and ideas are highly appreciated!非常感谢所有帮助、提示和想法!

Here we use RANK() OVER (PARTITION BY in a CTE to identify the rows that we want and then filter in the WHERE .在这里,我们在CTE中使用RANK() OVER (PARTITION BY来识别我们想要的行,然后在WHERE中进行过滤。
I have also modified the column names to replace spaces with an underscore which makes queries much easier to write.我还修改了列名,用下划线替换空格,这使得查询容易编写。
I've added valid_From to the order by in the Rank() to eliminate duplicate Valid_To value for United Kingdom.我已将 valid_From 添加到Rank()中的order by ,以消除英国的重复 Valid_To 值。

 CREATE TABLE PriceList ( [Country] VARCHAR(15), [Price_list] VARCHAR(25), [Item_number] INTEGER, [Price] DECIMAL(10, 2), [Valid_from] INTEGER, [Valid_to] INTEGER ); INSERT INTO PriceList ( Country, [Price_list], [Item_number], Price, [Valid_from], [Valid_to] ) VALUES ('United Kingdom', 'Price list Tech', 33333, 20.50, 20200101, 20201231), ('United Kingdom', 'Price list Tech', 33333, 20.50, 20200102, 20201231), ('Germany', 'Price list stuff', 44444, 15.50, 20200102, 20201231), ('Germany', 'Price list stuff', 44444, 15.50, 20200101, 20200630), ('USA', 'Price list textile new', 55555, 32.25, 20200102, 20201231), ('USA', 'Price list textile', 55555, 32.50, 20200101, 20200630), ('Germany', 'Price list stuff', 44444, 15.50, 20210101, 20210630); GO

7 rows affected 7 行受影响

select * from pricelist; GO
 Country |国家 | Price_list |价目表 | Item_number |项目编号 | Price |价格 | Valid_from |有效来源 | Valid_to:------------- |:--------------------- |有效_至:------------ |:-------------------- | ----------: | ----------: | ----: | ----: | ---------: | ----------: | -------: United Kingdom | -------:英国 | Price list Tech |价目表33333 | 33333 | 20.50 | 20.50 | 20200101 | 20200101 | 20201231 United Kingdom | 20201231 英国 | Price list Tech |价目表33333 | 33333 | 20.50 | 20.50 | 20200102 | 20200102 | 20201231 Germany | 20201231 德国 | Price list stuff |价目表的东西 | 44444 | 44444 | 15.50 | 15.50 | 20200102 | 20200102 | 20201231 Germany | 20201231 德国 | Price list stuff |价目表的东西 | 44444 | 44444 | 15.50 | 15.50 | 20200101 | 20200101 | 20200630 USA | 20200630 美国 | Price list textile new |价格表纺织品新| 55555 | 55555 | 32.25 | 32.25 | 20200102 | 20200102 | 20201231 USA | 20201231 美国 | Price list textile |纺织品价格表 | 55555 | 55555 | 32.50 | 32.50 | 20200101 | 20200101 | 20200630 Germany | 20200630 德国 | Price list stuff |价目表的东西 | 44444 | 44444 | 15.50 | 15.50 | 20210101 | 20210101 | 20210630 20210630
 WITH prices AS (SELECT Country, Item_Number, Price, Valid_From, Valid_To, RANK() OVER ( PARTITION BY Country,Item_Number ORDER BY Valid_To DESC, Valid_From )ranking FROM PriceList ) SELECT Country, Item_Number, Price, Valid_From, Valid_To FROM prices WHERE ranking = 1; GO
 Country |国家 | Item_Number |货品编号 | Price |价格 | Valid_From |有效发件人 | Valid_To:------------- |有效_至:-------------- | ----------: | ----------: | ----: | ----: | ---------: | ----------: | -------: Germany | -------:德国| 44444 | 44444 | 15.50 | 15.50 | 20210101 | 20210101 | 20210630 United Kingdom | 20210630 英国 | 33333 | 33333 | 20.50 | 20.50 | 20200101 | 20200101 | 20201231 USA | 20201231 美国 | 55555 | 55555 | 32.25 | 32.25 | 20200102 | 20200102 | 20201231 20201231

db<>fiddle here db<> 在这里摆弄

try this simplified query with [price list] / Country / Item / year (valid from)使用 [price list] / Country / Item / year试试这个简化的查询(有效期自)
the windowed function FIRST_VALUE() can do the trick along with distinct窗口化的 function FIRST_VALUE()可以和distinct一起解决这个问题

select distinct Country,[Item number]
       ,[year]       = [Valid from]/10000
       ,[Price List] = FIRST_VALUE([Price list])OVER(partition by Country,[Item number],[Valid from]/10000 order by [Valid from] desc)
       ,[price]      = FIRST_VALUE(Price)       OVER(partition by Country,[Item number],[Valid from]/10000 order by [Valid from] desc)
from  #PriceList

results:结果:

Country        | Item number | year | Price List             | price 
-------        | ----------- | -----| ---------------------- | ----- 
Germany        | 44444       | 2020 | Price list stuff       | 15.50
Germany        | 44444       | 2021 | Price list stuff       | 15.50
United Kingdom | 33333       | 2020 | Price list Tech        | 20.50
USA            | 55555       | 2020 | Price list textile new | 32.25

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM