仅从表A中选择日期比表B中的实际日期更近的预测数据

时间:2019-02-12 08:53:39

标签: sql sql-server

我有一个带有表结构的Forecast和Actuals表:

YearNb, WeekNb, Country, Product, Volume

现在,我正在处理具有将两者结合在一起的相同结构的第三个表。 我已经有一个查询,该查询只是导入所有实际值。现在,我需要导入所有相关的预测。这导致了我的问题。我只需要日期比实际日期更近的预测。 “预测”表包括所有历史预测,其中大多数都不相关。我需要在国家/地区级别进行此检查,因为我们在国家/地区级别上收到此数据,并且不同国家/地区的近期实际情况可能有所不同。

我已经做了:

WITH cte AS
(
   SELECT Country, YearNb, WeekNb, (YearNb*100 + WeekNb) AS Date,
         ROW_NUMBER() OVER (PARTITION BY Country ORDER BY (YearNb*100 + WeekNb) DESC) AS rn
   FROM Actuals
)
SELECT *
FROM cte
WHERE rn = 1

这为我提供了每个国家的分组列表,其中包含最新的实际数据日期。 但是现在我有点卡住了如何使用它来从具有最近日期的预测表中选择数据。

Country YearNb  WeekNb  Date
A       2018      29    201829
B       2019       5    201905  
C       2018      34    201834  

重要的一点是,我需要在产品级别上使用此数据,以便与原始两个表具有相同的结构。 因此,作为最终输出,我需要日期201829之后的国家A的所有产品的所有预测,日期201905之后的国家B的所有数据,等等。

4 个答案:

答案 0 :(得分:2)

尝试在field年之前加入,并添加条件以获取更早的日期:

SELECT
*
FROM Actuals act
INNER JOIN 
(
    SELECT
    (
    SELECT 
    Country, YearNb, WeekNb, (YearNb*100 + WeekNb) AS Date,
    ROW_NUMBER() OVER (PARTITION BY Country ORDER BY (YearNb*100 + WeekNb) DESC) AS rn
    FROM Actuals
    WHERE  ROW_NUMBER() OVER (PARTITION BY Country ORDER BY (YearNb*100 + WeekNb) DESC) = 1
    )
    WHERE RN = 1
)q ON act.YearNb = q.YearNb and (act.YearNb*100 + act.WeekNb) < q.Date

答案 1 :(得分:2)

我将对NOT EXISTS使用依赖查询

select YearNb, WeekNb, Country, Product, Volume
from Forecast f
where not exists (
  select 1
  from Actual a
  where a.country = f.country and
        a.YearNb * 100 + a.WeekNb >= f.YearNb * 100 + f.WeekNb
)

这将从您的Forecast表中选择相关数据。如果考虑性能,那么EXISTS属性上有一个索引,country的性能会更好。

编辑

如果您想忽略forecats个不在实际中的国家,请使用半联接

select f.*
from Forecast f    
where not exists (
  select 1
  from Actual a
  where a.country = f.country and
        a.YearNb * 100 + a.WeekNb >= f.YearNb * 100 + f.WeekNb
) and 
exists(
  select 1
  from Actual a
  where a.country = f.country
)

答案 2 :(得分:1)

使用您自己的CTE,您可以得到

WITH cte AS
(
   SELECT Country, YearNb, WeekNb, (YearNb*100 + WeekNb) AS Date,
         ROW_NUMBER() OVER (PARTITION BY Country ORDER BY (YearNb*100 + WeekNb) DESC) AS rn
   FROM Actuals
)
SELECT f.*
FROM forecast f
JOIN cte ON f.Country = cte.Country AND cte.date < (f.YearNb*100 + f.WeekNb)
WHERE cte.rn = 1

答案 3 :(得分:0)

我会使用cross apply

select f.*, a.*
from (select a.*,
             row_number() over (partition by country order by yearnb desc, weeknb desc) as seqnum
      from actuals a
     ) a cross apply
     (select f.*
      from forecast f
      where f.country = a.country and
            (f.yearnb > a.yearnb or
             f.yearnb = a.yearnb and f.weeknb > a.weeknb
            )
     ) f
where a.seqnum = 1;

这使得从两个表中选择列变得容易。