【问题标题】:Show data that takes into consideration consecutive weeks [closed]显示考虑到连续几周的数据[关闭]
【发布时间】:2022-01-27 09:47:42
【问题描述】:

你好我有这样的情况我基本上需要为这样的语句写一个SQL代码

select *,
    case when 'Issue' IN ('Overforecasted', 'Underforecasted') AND 'Start Date' DISTINCT 3 dates THEN 'Issue exists for 3 weeks in a row'
    FROM Merged;

我知道这不是正确的 SQL 格式,但有人知道如何编辑它吗?

每一个 DMDUNIT 检查它是否在“问题”列中有 3 个问题,然后检查它是否有 3 个不同的开始日期。如果它有 3 个问题(“预测过度”、“预测不足”)和同一 DMDUNIT 的 3 个不同日期,我需要在新列中返回它(以“3InARow”结尾)

当前编辑的草稿

 SET ARITHABORT OFF 
SET ANSI_WARNINGS OFF;


;WITH Forecast AS (
    SELECT LOC, DMDUNIT, STARTDATE, TOTFCST
    FROM SCPOMGR.FCSTPERFSTATIC
    WHERE STARTDATE >= '2021-11-24'
), Actuals AS (
    SELECT LOC, DMDUNIT, DMDPostDate, HistoryQuantity
    FROM SCPOMGR.HISTWIDE_CHAIN
    WHERE DMDPostDate >= '2021-11-24'

), Merged as (
    select
        COALESCE(f.LOC, a.LOC) AS LOC,
        COALESCE(f.DMDUNIT, a.DMDUNIT) AS DMDUNIT,
        COALESCE(f.STARTDATE, a.DMDPostDate) AS "Start Date",
        SUM(F.TOTFCST) AS "Forecast",
        SUM(a.HistoryQuantity) AS "Actuals",
        SUM(ABS(a.HistoryQuantity) - f.TOTFCST) AS "Abs Error",
        (1 - HistoryQuantity - TOTFCST) / HistoryQuantity as "FA%",
        SUM(a.HistoryQuantity) / SUM(f.TOTFCST) AS "Bias",       
        CASE
            WHEN TOTFCST > HistoryQuantity THEN 'Overforecasted' 
            WHEN TOTFCST < HistoryQuantity THEN 'Underforecasted'
            WHEN HistoryQuantity IS NULL AND TOTFCST > 0 THEN 'Overforecasted'
            WHEN TOTFCST IS NULL AND HistoryQuantity > 0 THEN 'Underforecasted'
            WHEN TOTFCST = 0.000 AND HistoryQuantity IS NULL THEN 'No issue'
        END AS Issue
    FROM Forecast f FULL OUTER JOIN Actuals a
        ON f.LOC = a.LOC AND f.DMDUNIT = a.DMDUNIT AND f.STARTDATE = a.DMDPostDate
         GROUP BY
        COALESCE(f.LOC, a.LOC),
        COALESCE(f.DMDUNIT, a.DMDUNIT),
        COALESCE(f.STARTDATE, a.DMDPostDate),
        a.HistoryQuantity, F.TOTFCST),
    Transitions as (
    select *, 
        case when indicator <> lag(indicator)
            over (partition by DMDUNIT order by "Start Date")
            then 1 end as tripped
    from Merged cross apply (
        select case when Issue in ('Overforecasted', 'Underforecasted') 
            then 1 else 0 end as indicator) v
), Bundles as (
    select *, count(tripped) over (partition by DMDUNIT order by "Start Date") as grp
    from Transitions
), Streaks as (
    select *, count(*) over (partition by DMDUNIT, grp) as cnt
    from Bundles
)
select *, case when indicator = 1 and cnt >= 3 then 'Yes' else 'No' end as InIssueStreak, cnt as StreakLength
from Streaks;

【问题讨论】:

  • @JonArmstrong 对不起,我不明白。添加架构将如何帮助我解决我的问题?你能不能调整一下代码,否则我不明白你想让我做什么......
  • 通过正式定义问题并提供您希望看到的确切行为示例来帮助他人帮助您。请参阅以下建议:meta.stackoverflow.com/questions/271055/…stackoverflow.com/help/minimal-reproducible-example
  • 首先纠正您的 SQL 引用的错误或未定义的对象。 dbfiddle.uk/…
  • @JonArmstrong 我使用 SSMS。我真的没有任何问题,例如“无效的对象名称 'SCPOMGR.FCSTPERFSTATIC'”。运行时。不确定该站点 dbfiddle 应该显示什么...

标签: sql ssms


【解决方案1】:
WITH Forecast AS (
    SELECT LOC, DMDUNIT, STARTDATE, TOTFCST
    FROM SCPOMGR.FCSTPERFSTATIC
    WHERE STARTDATE >= '2021-11-24'
), Actuals AS (
    SELECT LOC, DMDUNIT, DMDPostDate, HistoryQuantity
    FROM SCPOMGR.HISTWIDE_CHAIN
    WHERE DMDPostDate >= '2021-11-24'
), Merged AS (
    SELECT
        COALESCE(f.LOC, a.LOC) AS LOC,
        COALESCE(f.DMDUNIT, a.DMDUNIT) AS DMDUNIT,
        COALESCE(f.STARTDATE, a.DMDPostDate) AS "Start Date",
        SUM(F.TOTFCST) AS "Forecast",
        SUM(a.HistoryQuantity) AS "Actuals",
        SUM(ABS(a.HistoryQuantity) - f.TOTFCST) AS "Abs Error"
        (1 - SUM(a.HistoryQuantity - SUM(f.TOTFCST)) / SUM(a.HistoryQuantity) as "FA%",
        SUM(a.HistoryQuantity) / SUM(f.TOTFCST) AS "Bias",
        CASE
            WHEN SUM(f.TOTFCST) > SUM(a.HistoryQuantity) THEN 'Overforecasted' 
            WHEN SUM(f.TOTFCST) < SUM(a.HistoryQuantity) THEN 'Underforecasted'
            WHEN SUM(a.HistoryQuantity) IS NULL AND SUM(f.TOTFCST) > 0 THEN 'Overforecasted'
            WHEN SUM(f.TOTFCST) IS NULL AND SUM(a.HistoryQuantity) > 0 THEN 'Underforecasted'
            WHEN SUM(f.TOTFCST) = 0.000 AND SUM(a.HistoryQuantity) IS NULL THEN 'No issue'
        END AS Issue
    FROM Forecast f FULL OUTER JOIN Actuals a
        ON f.LOC = a.LOC AND f.DMDUNIT = a.DMDUNIT AND f.STARTDATE = a.DMDPostDate
    GROUP BY
        COALESCE(f.LOC, a.LOC),
        COALESCE(f.DMDUNIT, a.DMDUNIT),
        COALESCE(f.STARTDATE, a.DMDPostDate)
    ORDER BY
        COALESCE(f.LOC, a.LOC),
        COALESCE(f.DMDUNIT, a.DMDUNIT),
        COALESCE(f.STARTDATE, a.DMDPostDate)
)
select *,
    case when
        min(Issue) over (
            partition by DMDUNIT order by "Start Date"
            rows between 2 preceding and current row) =
        max(Issue) over (
            partition by DMDUNIT order by "Start Date"
            rows between 2 preceding and current row) and
        count(Issue) over (
            partition by DMDUNIT order by "Start Date"
            rows between 2 preceding and current row) = 3
        then 'Yes' else 'No' end as "3InARow"
from Merged;

如果这不起作用,请尝试间隙和孤岛:

with (<copied from above...>), Transitions as (
    select *, 
        case when indicator <> lag(indicator)
            over (partition by DMDINIT order by "Start Date")
            then 1 end as tripped
    from Merged cross apply (
        select case when Issue in ('Overforecasted', 'Underforecasted') 
            then 1 else 0 end as indicator) v
), Bundles as (
    select *, sum(tripped) over (partition by DMDUNIT order by "Start Date") as grp
    from Transitions
), Streaks as (
    select *, count(*) over (partition by DMDUNIT, grp) as cnt
    from Bundles
)
select *, case when cnt >= 3 then 'Yes' else 'No' end as InStreak, cnt as StreakLength
from Streaks;

https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=9fcbab1d93b7297aebc340111aa3a448

【讨论】:

  • 非常感谢!!我认为我们离我需要的更近了。我用的是第一个。但是,我认为 smth 不起作用,因为我需要为连续 3 周超过或低于预测的项目看到“是”。在我上面粘贴的示例中(对于 unit# 042229214912),我得到一周的“是”和另外两周的“否”。但我认为所有 3 周都应该是“是”,因为我们在第 1 周预测不足(预测 2.18,实际值 3),第 2 周预测不足(预测值 0.183 和实际值 7)和第 3 周(预测值 5.095)和 0 个实际值)。
  • 我已将屏幕截图发布到我的原始帖子中。
  • @Davidskis 我添加了另一个需要三行的条件。也许这会解决它。
  • @Davidskis 你只是在看预测的迹象吗?之前有一个 case 表达式返回一个文本值。
  • 我已将 CASE 语句再次添加到代码中(在帖子的开头)。不幸的是,'sgn' 不是 SSMS 中公认的内置函数名称,它不接受。我认为这个 CASE 语句应该查看“问题”列,如果它检测到“预测不足”或“过度预测”,还应该查看“开始日期”,如果是 3 周,则返回“是”。
【解决方案2】:

The fiddle

我创建了一个有效的测试用例,演示了如何识别连续几周的预测过高或过低的项目。

关于如何计算每周价值或如何识别项目的所有细节对于基本问题并不重要。我已经忽略了一周内与丢失数据有关的问题。这很容易被包含在内,只是掩盖了所提出的基本(也是唯一)问题。

对于这个例子,假设我们只有感兴趣的周并且所有项目的所有周都存在。

SQL,也包含数据:

WITH forecast (item, prediction) AS (
        SELECT 1, 1000 UNION
        SELECT 2,  500
     )
   , actuals (weekno, item, actual) AS (
        SELECT  1, 1,  500 UNION
        SELECT  2, 1,  600 UNION
        SELECT  3, 1, 1600 UNION
        SELECT  4, 1, 1600 UNION
        SELECT  5, 1,  600 UNION
        SELECT  6, 1, 1100 UNION
        SELECT  7, 1, 1200 UNION
        SELECT  8, 1, 1150 UNION
        SELECT  9, 1,  601 UNION
        SELECT 10, 1,  602 UNION
        SELECT 11, 1,  603 UNION
        SELECT  1, 2, 1500 UNION
        SELECT  2, 2,  600 UNION
        SELECT  3, 2,  550 UNION
        SELECT  4, 2,  500 UNION
        SELECT  5, 2,  600 UNION
        SELECT  6, 2,  491 UNION
        SELECT  7, 2,  492 UNION
        SELECT  8, 2,  493 UNION
        SELECT  9, 2,  494 UNION
        SELECT 10, 2,  620
     )
   , step1 AS (
        SELECT a.*
             , f.prediction
             , CASE WHEN actual < prediction THEN -1
                    WHEN actual > prediction THEN +1
                    ELSE 0
               END AS side
          FROM forecast AS f
          JOIN actuals  AS a
            ON f.item = a.item
     )
   , step2 AS (
        SELECT *
             , CASE WHEN side = LAG(side) OVER (PARTITION BY item ORDER BY weekno) THEN 0 ELSE 1 END AS edge
          FROM step1
     )
   , step3 AS (
        SELECT *
             , SUM(edge) OVER (PARTITION BY item ORDER BY weekno) AS xgroup
          FROM step2
     )
   , step4 AS (
        SELECT *
             , COUNT(*) OVER (PARTITION BY item, xgroup) AS xcount
          FROM step3
     )
SELECT *
  FROM step4
 WHERE xcount >= 3
 ORDER BY item, weekno
;

结果:

weekno item actual prediction side edge xgroup xcount
6 1 1100 1000 1 1 4 3
7 1 1200 1000 1 0 4 3
8 1 1150 1000 1 0 4 3
9 1 601 1000 -1 1 5 3
10 1 602 1000 -1 0 5 3
11 1 603 1000 -1 0 5 3
1 2 1500 500 1 1 1 3
2 2 600 500 1 0 1 3
3 2 550 500 1 0 1 3
6 2 491 500 -1 1 4 4
7 2 492 500 -1 0 4 4
8 2 493 500 -1 0 4 4
9 2 494 500 -1 0 4 4

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-07
    相关资源
    最近更新 更多