显示考虑连续几周的数据
Show data that takes into consideration consecutive weeks
你好我有这样的情况我基本上需要写一个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 个问题('Overforecasted'、“预测不足”)和同一个 DMDUNIT 的 3 个不同日期,我需要 return 它在一个新列中(以“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;
我创建了一个工作测试用例,它演示了如何识别连续几周超过或低于预测的项目。
关于如何计算每周价值或如何识别项目的所有细节对于基本问题都无关紧要。一周以来,我一直忽略与缺失数据相关的问题。这很容易包含在内,只是掩盖了所问的基本(也是唯一)问题。
对于这个例子,假设我们只有感兴趣的周,并且所有项目的所有周都存在。
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
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
你好我有这样的情况我基本上需要写一个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 个问题('Overforecasted'、“预测不足”)和同一个 DMDUNIT 的 3 个不同日期,我需要 return 它在一个新列中(以“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;
我创建了一个工作测试用例,它演示了如何识别连续几周超过或低于预测的项目。
关于如何计算每周价值或如何识别项目的所有细节对于基本问题都无关紧要。一周以来,我一直忽略与缺失数据相关的问题。这很容易包含在内,只是掩盖了所问的基本(也是唯一)问题。
对于这个例子,假设我们只有感兴趣的周,并且所有项目的所有周都存在。
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 |
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